From 088ec0cc96e2befd5f3c035123f95c17bdf26e64 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Tue, 6 Oct 2009 12:19:07 +0000 Subject: gigaset: prepare for CAPI implementation 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 Signed-off-by: David S. Miller --- drivers/isdn/gigaset/asyncdata.c | 124 +++++---- drivers/isdn/gigaset/bas-gigaset.c | 4 +- drivers/isdn/gigaset/common.c | 50 ++-- drivers/isdn/gigaset/ev-layer.c | 64 +++-- drivers/isdn/gigaset/gigaset.h | 90 ++----- drivers/isdn/gigaset/i4l.c | 506 ++++++++++++++++++++++--------------- drivers/isdn/gigaset/isocdata.c | 79 +++--- 7 files changed, 492 insertions(+), 425 deletions(-) (limited to 'drivers/isdn') 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, 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; @@ -158,8 +155,8 @@ byte_stuff: #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; @@ -170,54 +167,39 @@ byte_stuff: "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; @@ -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; + } } } @@ -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); @@ -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; @@ -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; @@ -515,15 +501,16 @@ 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; @@ -531,12 +518,15 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) 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; @@ -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, @@ -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"); diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 5ed1d99eb9f3..388e63a8ae94 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -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 */ @@ -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", diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 33dcd8d72b7c..15dc0fc28a96 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -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); @@ -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); @@ -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; @@ -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"); @@ -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; } @@ -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); diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index cc768caa38f5..cb25d2b834b9 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c @@ -127,7 +127,6 @@ #define ACT_NOTIFY_BC_UP 39 #define ACT_DIAL 40 #define ACT_ACCEPT 41 -#define ACT_PROTO_L2 42 #define ACT_HUP 43 #define ACT_IF_LOCK 44 #define ACT_START 45 @@ -365,8 +364,6 @@ struct reply_t gigaset_tab_cid[] = {EV_BC_CLOSED, -1, -1, -1, -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME /* misc. */ - {EV_PROTO_L2, -1, -1, -1, -1,-1, {ACT_PROTO_L2}}, //FIXME - {RSP_ZCON, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME {RSP_ZCCR, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME {RSP_ZAOC, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME @@ -714,7 +711,7 @@ static void disconnect(struct at_state_t **at_state_p) /* notify LL */ if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) { bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL); - gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP); + gigaset_isdn_hupD(bcs); } } else { /* no B channel assigned: just deallocate */ @@ -872,12 +869,12 @@ static void bchannel_down(struct bc_state *bcs) { if (bcs->chstate & CHS_B_UP) { bcs->chstate &= ~CHS_B_UP; - gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BHUP); + gigaset_isdn_hupB(bcs); } if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) { bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL); - gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP); + gigaset_isdn_hupD(bcs); } gigaset_free_channel(bcs); @@ -894,15 +891,16 @@ static void bchannel_up(struct bc_state *bcs) } bcs->chstate |= CHS_B_UP; - gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BCONN); + gigaset_isdn_connB(bcs); } static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_index) { struct bc_state *bcs = at_state->bcs; struct cardstate *cs = at_state->cs; - int retval; + char **commands = data; unsigned long flags; + int i; bcs->chstate |= CHS_NOTIFY_LL; @@ -913,10 +911,10 @@ static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_ind } spin_unlock_irqrestore(&cs->lock, flags); - retval = gigaset_isdn_setup_dial(at_state, data); - if (retval != 0) - goto error; - + for (i = 0; i < AT_NUM; ++i) { + kfree(bcs->commands[i]); + bcs->commands[i] = commands[i]; + } at_state->pending_commands |= PC_CID; gig_dbg(DEBUG_CMD, "Scheduling PC_CID"); @@ -924,6 +922,10 @@ static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_ind return; error: + for (i = 0; i < AT_NUM; ++i) { + kfree(commands[i]); + commands[i] = NULL; + } at_state->pending_commands |= PC_NOCID; gig_dbg(DEBUG_CMD, "Scheduling PC_NOCID"); cs->commands_pending = 1; @@ -933,20 +935,31 @@ error: static void start_accept(struct at_state_t *at_state) { struct cardstate *cs = at_state->cs; - int retval; + struct bc_state *bcs = at_state->bcs; + int i; - retval = gigaset_isdn_setup_accept(at_state); + for (i = 0; i < AT_NUM; ++i) { + kfree(bcs->commands[i]); + bcs->commands[i] = NULL; + } - if (retval == 0) { - at_state->pending_commands |= PC_ACCEPT; - gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT"); - cs->commands_pending = 1; - } else { + bcs->commands[AT_PROTO] = kmalloc(9, GFP_ATOMIC); + bcs->commands[AT_ISO] = kmalloc(9, GFP_ATOMIC); + if (!bcs->commands[AT_PROTO] || !bcs->commands[AT_ISO]) { + dev_err(at_state->cs->dev, "out of memory\n"); /* error reset */ at_state->pending_commands |= PC_HUP; gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); cs->commands_pending = 1; + return; } + + snprintf(bcs->commands[AT_PROTO], 9, "^SBPR=%u\r", bcs->proto2); + snprintf(bcs->commands[AT_ISO], 9, "^SISO=%u\r", bcs->channel + 1); + + at_state->pending_commands |= PC_ACCEPT; + gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT"); + cs->commands_pending = 1; } static void do_start(struct cardstate *cs) @@ -957,7 +970,7 @@ static void do_start(struct cardstate *cs) schedule_init(cs, MS_INIT); cs->isdn_up = 1; - gigaset_i4l_cmd(cs, ISDN_STAT_RUN); + gigaset_isdn_start(cs); // FIXME: not in locked mode // FIXME 2: only after init sequence @@ -975,7 +988,7 @@ static void finish_shutdown(struct cardstate *cs) /* Tell the LL that the device is not available .. */ if (cs->isdn_up) { cs->isdn_up = 0; - gigaset_i4l_cmd(cs, ISDN_STAT_STOP); + gigaset_isdn_stop(cs); } /* The rest is done by cleanup_cs () in user mode. */ @@ -1276,7 +1289,7 @@ static void do_action(int action, struct cardstate *cs, break; } bcs->chstate |= CHS_D_UP; - gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN); + gigaset_isdn_connD(bcs); cs->ops->init_bchannel(bcs); break; case ACT_DLE1: @@ -1284,7 +1297,7 @@ static void do_action(int action, struct cardstate *cs, bcs = cs->bcs + cs->curchannel; bcs->chstate |= CHS_D_UP; - gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN); + gigaset_isdn_connD(bcs); cs->ops->init_bchannel(bcs); break; case ACT_FAKEHUP: @@ -1474,11 +1487,6 @@ static void do_action(int action, struct cardstate *cs, case ACT_ACCEPT: start_accept(at_state); break; - case ACT_PROTO_L2: - gig_dbg(DEBUG_CMD, "set protocol to %u", - (unsigned) ev->parameter); - at_state->bcs->proto2 = ev->parameter; - break; case ACT_HUP: at_state->pending_commands |= PC_HUP; cs->commands_pending = 1; diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index a2f6125739eb..1185da2dbf61 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -40,7 +39,6 @@ #define MAX_REC_PARAMS 10 /* Max. number of params in response string */ #define MAX_RESP_SIZE 512 /* Max. size of a response string */ -#define HW_HDR_LEN 2 /* Header size used to store ack info */ #define MAX_EVENTS 64 /* size of event queue */ @@ -216,7 +214,6 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, #define EV_START -110 #define EV_STOP -111 #define EV_IF_LOCK -112 -#define EV_PROTO_L2 -113 #define EV_ACCEPT -114 #define EV_DIAL -115 #define EV_HUP -116 @@ -259,6 +256,11 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, #define SM_LOCKED 0 #define SM_ISDN 1 /* default */ +/* layer 2 protocols (AT^SBPR=...) */ +#define L2_BITSYNC 0 +#define L2_HDLC 1 +#define L2_VOICE 2 + struct gigaset_ops; struct gigaset_driver; @@ -395,7 +397,7 @@ struct bc_state { unsigned chstate; /* bitmap (CHS_*) */ int ignore; - unsigned proto2; /* Layer 2 protocol (ISDN_PROTO_L2_*) */ + unsigned proto2; /* layer 2 protocol (L2_*) */ char *commands[AT_NUM]; /* see AT_XXXX */ #ifdef CONFIG_GIGASET_DEBUG @@ -456,12 +458,13 @@ struct cardstate { unsigned running; /* !=0 if events are handled */ unsigned connected; /* !=0 if hardware is connected */ - unsigned isdn_up; /* !=0 after ISDN_STAT_RUN */ + unsigned isdn_up; /* !=0 after gigaset_isdn_start() */ unsigned cidmode; int myid; /* id for communication with LL */ - isdn_if iif; + void *iif; /* LL interface structure */ + unsigned short hw_hdr_len; /* headroom needed in data skbs */ struct reply_t *tabnocid; struct reply_t *tabcid; @@ -616,7 +619,9 @@ struct gigaset_ops { int (*baud_rate)(struct cardstate *cs, unsigned cflag); int (*set_line_ctrl)(struct cardstate *cs, unsigned cflag); - /* Called from i4l.c to put an skb into the send-queue. */ + /* Called from LL interface to put an skb into the send-queue. + * After sending is completed, gigaset_skb_sent() must be called + * with the first cs->hw_hdr_len bytes of skb->head preserved. */ int (*send_skb)(struct bc_state *bcs, struct sk_buff *skb); /* Called from ev-layer.c to process a block of data @@ -638,8 +643,7 @@ struct gigaset_ops { * Functions implemented in asyncdata.c */ -/* Called from i4l.c to put an skb into the send-queue. - * After sending gigaset_skb_sent() should be called. */ +/* Called from LL interface to put an skb into the send queue. */ int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb); /* Called from ev-layer.c to process a block of data @@ -650,8 +654,7 @@ void gigaset_m10x_input(struct inbuf_t *inbuf); * Functions implemented in isocdata.c */ -/* Called from i4l.c to put an skb into the send-queue. - * After sending gigaset_skb_sent() should be called. */ +/* Called from LL interface to put an skb into the send queue. */ int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb); /* Called from ev-layer.c to process a block of data @@ -674,36 +677,26 @@ void gigaset_isowbuf_init(struct isowbuf_t *iwb, unsigned char idle); int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size); /* =========================================================================== - * Functions implemented in i4l.c/gigaset.h + * Functions implemented in LL interface */ -/* Called by gigaset_initcs() for setting up with the isdn4linux subsystem */ -int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid); +/* Called from common.c for setting up/shutting down with the ISDN subsystem */ +int gigaset_isdn_register(struct cardstate *cs, const char *isdnid); +void gigaset_isdn_unregister(struct cardstate *cs); -/* Called from xxx-gigaset.c to indicate completion of sending an skb */ +/* Called from hardware module to indicate completion of an skb */ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb); +void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb); +void gigaset_isdn_rcv_err(struct bc_state *bcs); /* Called from common.c/ev-layer.c to indicate events relevant to the LL */ +void gigaset_isdn_start(struct cardstate *cs); +void gigaset_isdn_stop(struct cardstate *cs); int gigaset_isdn_icall(struct at_state_t *at_state); -int gigaset_isdn_setup_accept(struct at_state_t *at_state); -int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data); - -void gigaset_i4l_cmd(struct cardstate *cs, int cmd); -void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd); - - -static inline void gigaset_isdn_rcv_err(struct bc_state *bcs) -{ - isdn_ctrl response; - - /* error -> LL */ - gig_dbg(DEBUG_CMD, "sending L1ERR"); - response.driver = bcs->cs->myid; - response.command = ISDN_STAT_L1ERR; - response.arg = bcs->channel; - response.parm.errcode = ISDN_STAT_L1ERR_RECV; - bcs->cs->iif.statcallb(&response); -} +void gigaset_isdn_connD(struct bc_state *bcs); +void gigaset_isdn_hupD(struct bc_state *bcs); +void gigaset_isdn_connB(struct bc_state *bcs); +void gigaset_isdn_hupB(struct bc_state *bcs); /* =========================================================================== * Functions implemented in ev-layer.c @@ -816,35 +809,6 @@ static inline void gigaset_bchannel_up(struct bc_state *bcs) /* handling routines for sk_buff */ /* ============================= */ -/* pass received skb to LL - * Warning: skb must not be accessed anymore! - */ -static inline void gigaset_rcv_skb(struct sk_buff *skb, - struct cardstate *cs, - struct bc_state *bcs) -{ - cs->iif.rcvcallb_skb(cs->myid, bcs->channel, skb); - bcs->trans_down++; -} - -/* handle reception of corrupted skb - * Warning: skb must not be accessed anymore! - */ -static inline void gigaset_rcv_error(struct sk_buff *procskb, - struct cardstate *cs, - struct bc_state *bcs) -{ - if (procskb) - dev_kfree_skb(procskb); - - if (bcs->ignore) - --bcs->ignore; - else { - ++bcs->corrupted; - gigaset_isdn_rcv_err(bcs); - } -} - /* append received bytes to inbuf */ int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, unsigned numbytes); diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c index 654489d836cd..aca72a06184e 100644 --- a/drivers/isdn/gigaset/i4l.c +++ b/drivers/isdn/gigaset/i4l.c @@ -14,6 +14,9 @@ */ #include "gigaset.h" +#include + +#define HW_HDR_LEN 2 /* Header size used to store ack info */ /* == Handling of I4L IO =====================================================*/ @@ -95,6 +98,7 @@ static int writebuf_from_LL(int driverID, int channel, int ack, */ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) { + isdn_if *iif = bcs->cs->iif; unsigned len; isdn_ctrl response; @@ -114,71 +118,177 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) response.command = ISDN_STAT_BSENT; response.arg = bcs->channel; response.parm.length = len; - bcs->cs->iif.statcallb(&response); + iif->statcallb(&response); } } EXPORT_SYMBOL_GPL(gigaset_skb_sent); +/** + * gigaset_skb_rcvd() - pass received skb to LL + * @bcs: B channel descriptor structure. + * @skb: received data. + * + * Called by hardware module {bas,ser,usb}_gigaset when user data has + * been successfully received, for passing to the LL. + * Warning: skb must not be accessed anymore! + */ +void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb) +{ + isdn_if *iif = bcs->cs->iif; + + iif->rcvcallb_skb(bcs->cs->myid, bcs->channel, skb); + bcs->trans_down++; +} +EXPORT_SYMBOL_GPL(gigaset_skb_rcvd); + +/** + * gigaset_isdn_rcv_err() - signal receive error + * @bcs: B channel descriptor structure. + * + * Called by hardware module {bas,ser,usb}_gigaset when a receive error + * has occurred, for signalling to the LL. + */ +void gigaset_isdn_rcv_err(struct bc_state *bcs) +{ + isdn_if *iif = bcs->cs->iif; + isdn_ctrl response; + + /* if currently ignoring packets, just count down */ + if (bcs->ignore) { + bcs->ignore--; + return; + } + + /* update statistics */ + bcs->corrupted++; + + /* error -> LL */ + gig_dbg(DEBUG_CMD, "sending L1ERR"); + response.driver = bcs->cs->myid; + response.command = ISDN_STAT_L1ERR; + response.arg = bcs->channel; + response.parm.errcode = ISDN_STAT_L1ERR_RECV; + iif->statcallb(&response); +} +EXPORT_SYMBOL_GPL(gigaset_isdn_rcv_err); + /* This function will be called by LL to send commands * NOTE: LL ignores the returned value, for commands other than ISDN_CMD_IOCTL, * so don't put too much effort into it. */ static int command_from_LL(isdn_ctrl *cntrl) { - struct cardstate *cs = gigaset_get_cs_by_id(cntrl->driver); + struct cardstate *cs; struct bc_state *bcs; int retval = 0; - struct setup_parm *sp; + char **commands; + int ch; + int i; + size_t l; gigaset_debugdrivers(); - if (!cs) { + gig_dbg(DEBUG_CMD, "driver: %d, command: %d, arg: 0x%lx", + cntrl->driver, cntrl->command, cntrl->arg); + + cs = gigaset_get_cs_by_id(cntrl->driver); + if (cs == NULL) { pr_err("%s: invalid driver ID (%d)\n", __func__, cntrl->driver); return -ENODEV; } + ch = cntrl->arg & 0xff; switch (cntrl->command) { case ISDN_CMD_IOCTL: - gig_dbg(DEBUG_ANY, "ISDN_CMD_IOCTL (driver: %d, arg: %ld)", - cntrl->driver, cntrl->arg); - dev_warn(cs->dev, "ISDN_CMD_IOCTL not supported\n"); return -EINVAL; case ISDN_CMD_DIAL: gig_dbg(DEBUG_ANY, - "ISDN_CMD_DIAL (driver: %d, ch: %ld, " - "phone: %s, ownmsn: %s, si1: %d, si2: %d)", - cntrl->driver, cntrl->arg, + "ISDN_CMD_DIAL (phone: %s, msn: %s, si1: %d, si2: %d)", cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn, cntrl->parm.setup.si1, cntrl->parm.setup.si2); - if (cntrl->arg >= cs->channels) { + if (ch >= cs->channels) { dev_err(cs->dev, - "ISDN_CMD_DIAL: invalid channel (%d)\n", - (int) cntrl->arg); + "ISDN_CMD_DIAL: invalid channel (%d)\n", ch); return -EINVAL; } - - bcs = cs->bcs + cntrl->arg; - + bcs = cs->bcs + ch; if (!gigaset_get_channel(bcs)) { dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n"); return -EBUSY; } - sp = kmalloc(sizeof *sp, GFP_ATOMIC); - if (!sp) { + commands = kzalloc(AT_NUM*(sizeof *commands), GFP_ATOMIC); + if (!commands) { gigaset_free_channel(bcs); dev_err(cs->dev, "ISDN_CMD_DIAL: out of memory\n"); return -ENOMEM; } - *sp = cntrl->parm.setup; - if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, sp, + l = 3 + strlen(cntrl->parm.setup.phone); + commands[AT_DIAL] = kmalloc(l, GFP_ATOMIC); + if (!commands[AT_DIAL]) + goto oom; + if (cntrl->parm.setup.phone[0] == '*' && + cntrl->parm.setup.phone[1] == '*') { + /* internal call: translate ** prefix to CTP value */ + commands[AT_TYPE] = kstrdup("^SCTP=0\r", GFP_ATOMIC); + if (!commands[AT_TYPE]) + goto oom; + snprintf(commands[AT_DIAL], l, + "D%s\r", cntrl->parm.setup.phone+2); + } else { + commands[AT_TYPE] = kstrdup("^SCTP=1\r", GFP_ATOMIC); + if (!commands[AT_TYPE]) + goto oom; + snprintf(commands[AT_DIAL], l, + "D%s\r", cntrl->parm.setup.phone); + } + + l = strlen(cntrl->parm.setup.eazmsn); + if (l) { + l += 8; + commands[AT_MSN] = kmalloc(l, GFP_ATOMIC); + if (!commands[AT_MSN]) + goto oom; + snprintf(commands[AT_MSN], l, "^SMSN=%s\r", + cntrl->parm.setup.eazmsn); + } + + switch (cntrl->parm.setup.si1) { + case 1: /* audio */ + /* BC = 9090A3: 3.1 kHz audio, A-law */ + commands[AT_BC] = kstrdup("^SBC=9090A3\r", GFP_ATOMIC); + if (!commands[AT_BC]) + goto oom; + break; + case 7: /* data */ + default: /* hope the app knows what it is doing */ + /* BC = 8890: unrestricted digital information */ + commands[AT_BC] = kstrdup("^SBC=8890\r", GFP_ATOMIC); + if (!commands[AT_BC]) + goto oom; + } + /* ToDo: other si1 values, inspect si2, set HLC/LLC */ + + commands[AT_PROTO] = kmalloc(9, GFP_ATOMIC); + if (!commands[AT_PROTO]) + goto oom; + snprintf(commands[AT_PROTO], 9, "^SBPR=%u\r", bcs->proto2); + + commands[AT_ISO] = kmalloc(9, GFP_ATOMIC); + if (!commands[AT_ISO]) + goto oom; + snprintf(commands[AT_ISO], 9, "^SISO=%u\r", + (unsigned) bcs->channel + 1); + + if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, commands, bcs->at_state.seq_index, NULL)) { - //FIXME what should we do? - kfree(sp); + for (i = 0; i < AT_NUM; ++i) + kfree(commands[i]); + kfree(commands); gigaset_free_channel(bcs); return -ENOMEM; } @@ -186,93 +296,83 @@ static int command_from_LL(isdn_ctrl *cntrl) gig_dbg(DEBUG_CMD, "scheduling DIAL"); gigaset_schedule_event(cs); break; - case ISDN_CMD_ACCEPTD: //FIXME - gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTD"); - - if (cntrl->arg >= cs->channels) { + case ISDN_CMD_ACCEPTD: + if (ch >= cs->channels) { dev_err(cs->dev, - "ISDN_CMD_ACCEPTD: invalid channel (%d)\n", - (int) cntrl->arg); + "ISDN_CMD_ACCEPTD: invalid channel (%d)\n", ch); return -EINVAL; } - - if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state, - EV_ACCEPT, NULL, 0, NULL)) { - //FIXME what should we do? + bcs = cs->bcs + ch; + if (!gigaset_add_event(cs, &bcs->at_state, + EV_ACCEPT, NULL, 0, NULL)) return -ENOMEM; - } gig_dbg(DEBUG_CMD, "scheduling ACCEPT"); gigaset_schedule_event(cs); break; case ISDN_CMD_ACCEPTB: - gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTB"); break; case ISDN_CMD_HANGUP: - gig_dbg(DEBUG_ANY, "ISDN_CMD_HANGUP (ch: %d)", - (int) cntrl->arg); - - if (cntrl->arg >= cs->channels) { + if (ch >= cs->channels) { dev_err(cs->dev, - "ISDN_CMD_HANGUP: invalid channel (%d)\n", - (int) cntrl->arg); + "ISDN_CMD_HANGUP: invalid channel (%d)\n", ch); return -EINVAL; } - - if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state, - EV_HUP, NULL, 0, NULL)) { - //FIXME what should we do? + bcs = cs->bcs + ch; + if (!gigaset_add_event(cs, &bcs->at_state, + EV_HUP, NULL, 0, NULL)) return -ENOMEM; - } gig_dbg(DEBUG_CMD, "scheduling HUP"); gigaset_schedule_event(cs); break; - case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */ //FIXME - gig_dbg(DEBUG_ANY, "ISDN_CMD_CLREAZ"); + case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */ + dev_info(cs->dev, "ignoring ISDN_CMD_CLREAZ\n"); break; - case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */ //FIXME - gig_dbg(DEBUG_ANY, - "ISDN_CMD_SETEAZ (id: %d, ch: %ld, number: %s)", - cntrl->driver, cntrl->arg, cntrl->parm.num); + case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */ + dev_info(cs->dev, "ignoring ISDN_CMD_SETEAZ (%s)\n", + cntrl->parm.num); break; case ISDN_CMD_SETL2: /* Set L2 to given protocol */ - gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL2 (ch: %ld, proto: %lx)", - cntrl->arg & 0xff, (cntrl->arg >> 8)); - - if ((cntrl->arg & 0xff) >= cs->channels) { + if (ch >= cs->channels) { dev_err(cs->dev, - "ISDN_CMD_SETL2: invalid channel (%d)\n", - (int) cntrl->arg & 0xff); + "ISDN_CMD_SETL2: invalid channel (%d)\n", ch); return -EINVAL; } - - if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg & 0xff].at_state, - EV_PROTO_L2, NULL, cntrl->arg >> 8, - NULL)) { - //FIXME what should we do? - return -ENOMEM; + bcs = cs->bcs + ch; + if (bcs->chstate & CHS_D_UP) { + dev_err(cs->dev, + "ISDN_CMD_SETL2: channel active (%d)\n", ch); + return -EINVAL; + } + switch (cntrl->arg >> 8) { + case ISDN_PROTO_L2_HDLC: + gig_dbg(DEBUG_CMD, "ISDN_CMD_SETL2: setting L2_HDLC"); + bcs->proto2 = L2_HDLC; + break; + case ISDN_PROTO_L2_TRANS: + gig_dbg(DEBUG_CMD, "ISDN_CMD_SETL2: setting L2_VOICE"); + bcs->proto2 = L2_VOICE; + break; + default: + dev_err(cs->dev, + "ISDN_CMD_SETL2: unsupported protocol (%lu)\n", + cntrl->arg >> 8); + return -EINVAL; } - - gig_dbg(DEBUG_CMD, "scheduling PROTO_L2"); - gigaset_schedule_event(cs); break; case ISDN_CMD_SETL3: /* Set L3 to given protocol */ - gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL3 (ch: %ld, proto: %lx)", - cntrl->arg & 0xff, (cntrl->arg >> 8)); - - if ((cntrl->arg & 0xff) >= cs->channels) { + if (ch >= cs->channels) { dev_err(cs->dev, - "ISDN_CMD_SETL3: invalid channel (%d)\n", - (int) cntrl->arg & 0xff); + "ISDN_CMD_SETL3: invalid channel (%d)\n", ch); return -EINVAL; } if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) { dev_err(cs->dev, - "ISDN_CMD_SETL3: invalid protocol %lu\n", + "ISDN_CMD_SETL3: unsupported protocol (%lu)\n", cntrl->arg >> 8); return -EINVAL; } @@ -324,149 +424,34 @@ static int command_from_LL(isdn_ctrl *cntrl) } return retval; + +oom: + dev_err(bcs->cs->dev, "out of memory\n"); + for (i = 0; i < AT_NUM; ++i) + kfree(commands[i]); + return -ENOMEM; } -void gigaset_i4l_cmd(struct cardstate *cs, int cmd) +static void gigaset_i4l_cmd(struct cardstate *cs, int cmd) { + isdn_if *iif = cs->iif; isdn_ctrl command; command.driver = cs->myid; command.command = cmd; command.arg = 0; - cs->iif.statcallb(&command); + iif->statcallb(&command); } -void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd) +static void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd) { + isdn_if *iif = bcs->cs->iif; isdn_ctrl command; command.driver = bcs->cs->myid; command.command = cmd; command.arg = bcs->channel; - bcs->cs->iif.statcallb(&command); -} - -int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data) -{ - struct bc_state *bcs = at_state->bcs; - unsigned proto; - const char *bc; - size_t length[AT_NUM]; - size_t l; - int i; - struct setup_parm *sp = data; - - switch (bcs->proto2) { - case ISDN_PROTO_L2_HDLC: - proto = 1; /* 0: Bitsynchron, 1: HDLC, 2: voice */ - break; - case ISDN_PROTO_L2_TRANS: - proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */ - break; - default: - dev_err(bcs->cs->dev, "%s: invalid L2 protocol: %u\n", - __func__, bcs->proto2); - return -EINVAL; - } - - switch (sp->si1) { - case 1: /* audio */ - bc = "9090A3"; /* 3.1 kHz audio, A-law */ - break; - case 7: /* data */ - default: /* hope the app knows what it is doing */ - bc = "8890"; /* unrestricted digital information */ - } - //FIXME add missing si1 values from 1TR6, inspect si2, set HLC/LLC - - length[AT_DIAL ] = 1 + strlen(sp->phone) + 1 + 1; - l = strlen(sp->eazmsn); - length[AT_MSN ] = l ? 6 + l + 1 + 1 : 0; - length[AT_BC ] = 5 + strlen(bc) + 1 + 1; - length[AT_PROTO] = 6 + 1 + 1 + 1; /* proto: 1 character */ - length[AT_ISO ] = 6 + 1 + 1 + 1; /* channel: 1 character */ - length[AT_TYPE ] = 6 + 1 + 1 + 1; /* call type: 1 character */ - length[AT_HLC ] = 0; - - for (i = 0; i < AT_NUM; ++i) { - kfree(bcs->commands[i]); - bcs->commands[i] = NULL; - if (length[i] && - !(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) { - dev_err(bcs->cs->dev, "out of memory\n"); - return -ENOMEM; - } - } - - /* type = 1: extern, 0: intern, 2: recall, 3: door, 4: centrex */ - if (sp->phone[0] == '*' && sp->phone[1] == '*') { - /* internal call: translate ** prefix to CTP value */ - snprintf(bcs->commands[AT_DIAL], length[AT_DIAL], - "D%s\r", sp->phone+2); - strncpy(bcs->commands[AT_TYPE], "^SCTP=0\r", length[AT_TYPE]); - } else { - snprintf(bcs->commands[AT_DIAL], length[AT_DIAL], - "D%s\r", sp->phone); - strncpy(bcs->commands[AT_TYPE], "^SCTP=1\r", length[AT_TYPE]); - } - - if (bcs->commands[AT_MSN]) - snprintf(bcs->commands[AT_MSN], length[AT_MSN], - "^SMSN=%s\r", sp->eazmsn); - snprintf(bcs->commands[AT_BC ], length[AT_BC ], - "^SBC=%s\r", bc); - snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], - "^SBPR=%u\r", proto); - snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], - "^SISO=%u\r", (unsigned)bcs->channel + 1); - - return 0; -} - -int gigaset_isdn_setup_accept(struct at_state_t *at_state) -{ - unsigned proto; - size_t length[AT_NUM]; - int i; - struct bc_state *bcs = at_state->bcs; - - switch (bcs->proto2) { - case ISDN_PROTO_L2_HDLC: - proto = 1; /* 0: Bitsynchron, 1: HDLC, 2: voice */ - break; - case ISDN_PROTO_L2_TRANS: - proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */ - break; - default: - dev_err(at_state->cs->dev, "%s: invalid protocol: %u\n", - __func__, bcs->proto2); - return -EINVAL; - } - - length[AT_DIAL ] = 0; - length[AT_MSN ] = 0; - length[AT_BC ] = 0; - length[AT_PROTO] = 6 + 1 + 1 + 1; /* proto: 1 character */ - length[AT_ISO ] = 6 + 1 + 1 + 1; /* channel: 1 character */ - length[AT_TYPE ] = 0; - length[AT_HLC ] = 0; - - for (i = 0; i < AT_NUM; ++i) { - kfree(bcs->commands[i]); - bcs->commands[i] = NULL; - if (length[i] && - !(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) { - dev_err(at_state->cs->dev, "out of memory\n"); - return -ENOMEM; - } - } - - snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], - "^SBPR=%u\r", proto); - snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], - "^SISO=%u\r", (unsigned) bcs->channel + 1); - - return 0; + iif->statcallb(&command); } /** @@ -482,6 +467,7 @@ int gigaset_isdn_icall(struct at_state_t *at_state) { struct cardstate *cs = at_state->cs; struct bc_state *bcs = at_state->bcs; + isdn_if *iif = cs->iif; isdn_ctrl response; int retval; @@ -531,7 +517,7 @@ int gigaset_isdn_icall(struct at_state_t *at_state) response.arg = bcs->channel; //FIXME } response.driver = cs->myid; - retval = cs->iif.statcallb(&response); + retval = iif->statcallb(&response); gig_dbg(DEBUG_CMD, "Response: %d", retval); switch (retval) { case 0: /* no takers */ @@ -560,16 +546,109 @@ int gigaset_isdn_icall(struct at_state_t *at_state) } } -/* Set Callback function pointer */ -int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid) +/** + * gigaset_isdn_connD() - signal D channel connect + * @bcs: B channel descriptor structure. + * + * Called by main module to notify the LL that the D channel connection has + * been established. + */ +void gigaset_isdn_connD(struct bc_state *bcs) { - isdn_if *iif = &cs->iif; + gig_dbg(DEBUG_CMD, "sending DCONN"); + gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN); +} - gig_dbg(DEBUG_ANY, "Register driver capabilities to LL"); +/** + * gigaset_isdn_hupD() - signal D channel hangup + * @bcs: B channel descriptor structure. + * + * Called by main module to notify the LL that the D channel connection has + * been shut down. + */ +void gigaset_isdn_hupD(struct bc_state *bcs) +{ + gig_dbg(DEBUG_CMD, "sending DHUP"); + gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP); +} + +/** + * gigaset_isdn_connB() - signal B channel connect + * @bcs: B channel descriptor structure. + * + * Called by main module to notify the LL that the B channel connection has + * been established. + */ +void gigaset_isdn_connB(struct bc_state *bcs) +{ + gig_dbg(DEBUG_CMD, "sending BCONN"); + gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BCONN); +} + +/** + * gigaset_isdn_hupB() - signal B channel hangup + * @bcs: B channel descriptor structure. + * + * Called by main module to notify the LL that the B channel connection has + * been shut down. + */ +void gigaset_isdn_hupB(struct bc_state *bcs) +{ + gig_dbg(DEBUG_CMD, "sending BHUP"); + gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BHUP); +} + +/** + * gigaset_isdn_start() - signal device availability + * @cs: device descriptor structure. + * + * Called by main module to notify the LL that the device is available for + * use. + */ +void gigaset_isdn_start(struct cardstate *cs) +{ + gig_dbg(DEBUG_CMD, "sending RUN"); + gigaset_i4l_cmd(cs, ISDN_STAT_RUN); +} + +/** + * gigaset_isdn_stop() - signal device unavailability + * @cs: device descriptor structure. + * + * Called by main module to notify the LL that the device is no longer + * available for use. + */ +void gigaset_isdn_stop(struct cardstate *cs) +{ + gig_dbg(DEBUG_CMD, "sending STOP"); + gigaset_i4l_cmd(cs, ISDN_STAT_STOP); +} + +/** + * gigaset_isdn_register() - register to LL + * @cs: device descriptor structure. + * @isdnid: device name. + * + * Called by main module to register the device with the LL. + * + * Return value: 1 for success, 0 for failure + */ +int gigaset_isdn_register(struct cardstate *cs, const char *isdnid) +{ + isdn_if *iif; + + pr_info("ISDN4Linux interface\n"); + + iif = kmalloc(sizeof *iif, GFP_KERNEL); + if (!iif) { + pr_err("out of memory\n"); + return 0; + } if (snprintf(iif->id, sizeof iif->id, "%s_%u", isdnid, cs->minor_index) >= sizeof iif->id) { pr_err("ID too long: %s\n", isdnid); + kfree(iif); return 0; } @@ -593,9 +672,26 @@ int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid) if (!register_isdn(iif)) { pr_err("register_isdn failed\n"); + kfree(iif); return 0; } + cs->iif = iif; cs->myid = iif->channels; /* Set my device id */ + cs->hw_hdr_len = HW_HDR_LEN; return 1; } + +/** + * gigaset_isdn_unregister() - unregister from LL + * @cs: device descriptor structure. + * + * Called by main module to unregister the device from the LL. + */ +void gigaset_isdn_unregister(struct cardstate *cs) +{ + gig_dbg(DEBUG_CMD, "sending UNLOAD"); + gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD); + kfree(cs->iif); + cs->iif = NULL; +} diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index 9f3ef7b4248c..7dabfd35874c 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c @@ -500,7 +500,7 @@ int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len) int result; switch (bcs->proto2) { - case ISDN_PROTO_L2_HDLC: + case L2_HDLC: result = hdlc_buildframe(bcs->hw.bas->isooutbuf, in, len); gig_dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d", __func__, len, result); @@ -542,8 +542,9 @@ static inline void hdlc_flush(struct bc_state *bcs) if (likely(bcs->skb != NULL)) skb_trim(bcs->skb, 0); else if (!bcs->ignore) { - if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) - skb_reserve(bcs->skb, HW_HDR_LEN); + bcs->skb = dev_alloc_skb(SBUFSIZE + bcs->cs->hw_hdr_len); + if (bcs->skb) + skb_reserve(bcs->skb, bcs->cs->hw_hdr_len); else dev_err(bcs->cs->dev, "could not allocate skb\n"); } @@ -557,7 +558,9 @@ static inline void hdlc_flush(struct bc_state *bcs) */ static inline void hdlc_done(struct bc_state *bcs) { + struct cardstate *cs = bcs->cs; struct sk_buff *procskb; + unsigned int len; if (unlikely(bcs->ignore)) { bcs->ignore--; @@ -568,32 +571,33 @@ static inline void hdlc_done(struct bc_state *bcs) if ((procskb = bcs->skb) == NULL) { /* previous error */ gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__); - gigaset_rcv_error(NULL, bcs->cs, bcs); + gigaset_isdn_rcv_err(bcs); } else if (procskb->len < 2) { - dev_notice(bcs->cs->dev, "received short frame (%d octets)\n", + dev_notice(cs->dev, "received short frame (%d octets)\n", procskb->len); bcs->hw.bas->runts++; - gigaset_rcv_error(procskb, bcs->cs, bcs); + dev_kfree_skb(procskb); + gigaset_isdn_rcv_err(bcs); } else if (bcs->fcs != PPP_GOODFCS) { - dev_notice(bcs->cs->dev, "frame check error (0x%04x)\n", - bcs->fcs); + dev_notice(cs->dev, "frame check error (0x%04x)\n", bcs->fcs); bcs->hw.bas->fcserrs++; - gigaset_rcv_error(procskb, bcs->cs, bcs); + dev_kfree_skb(procskb); + gigaset_isdn_rcv_err(bcs); } else { - procskb->len -= 2; /* subtract FCS */ - procskb->tail -= 2; - gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)", - __func__, procskb->len); + len = procskb->len; + __skb_trim(procskb, len -= 2); /* subtract FCS */ + gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)", __func__, len); dump_bytes(DEBUG_STREAM_DUMP, - "rcv data", procskb->data, procskb->len); - bcs->hw.bas->goodbytes += procskb->len; - gigaset_rcv_skb(procskb, bcs->cs, bcs); + "rcv data", procskb->data, len); + bcs->hw.bas->goodbytes += len; + gigaset_skb_rcvd(bcs, procskb); } - if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) - skb_reserve(bcs->skb, HW_HDR_LEN); + bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); + if (bcs->skb) + skb_reserve(bcs->skb, cs->hw_hdr_len); else - dev_err(bcs->cs->dev, "could not allocate skb\n"); + dev_err(cs->dev, "could not allocate skb\n"); bcs->fcs = PPP_INITFCS; } @@ -610,12 +614,8 @@ static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits) dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits); bcs->hw.bas->alignerrs++; - gigaset_rcv_error(bcs->skb, bcs->cs, bcs); - - if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) - skb_reserve(bcs->skb, HW_HDR_LEN); - else - dev_err(bcs->cs->dev, "could not allocate skb\n"); + gigaset_isdn_rcv_err(bcs); + __skb_trim(bcs->skb, 0); bcs->fcs = PPP_INITFCS; } @@ -648,8 +648,8 @@ static const unsigned char bitcounts[256] = { /* hdlc_unpack * perform HDLC frame processing (bit unstuffing, flag detection, FCS calculation) * on a sequence of received data bytes (8 bits each, LSB first) - * pass on successfully received, complete frames as SKBs via gigaset_rcv_skb - * notify of errors via gigaset_rcv_error + * pass on successfully received, complete frames as SKBs via gigaset_skb_rcvd + * notify of errors via gigaset_isdn_rcv_err * tally frames, errors etc. in BC structure counters * parameters: * src received data @@ -841,7 +841,7 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, } /* trans_receive - * pass on received USB frame transparently as SKB via gigaset_rcv_skb + * pass on received USB frame transparently as SKB via gigaset_skb_rcvd * invert bytes * tally frames, errors etc. in BC structure counters * parameters: @@ -852,6 +852,7 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, static inline void trans_receive(unsigned char *src, unsigned count, struct bc_state *bcs) { + struct cardstate *cs = bcs->cs; struct sk_buff *skb; int dobytes; unsigned char *dst; @@ -862,12 +863,12 @@ static inline void trans_receive(unsigned char *src, unsigned count, return; } if (unlikely((skb = bcs->skb) == NULL)) { - bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN); + bcs->skb = skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); if (!skb) { - dev_err(bcs->cs->dev, "could not allocate skb\n"); + dev_err(cs->dev, "could not allocate skb\n"); return; } - skb_reserve(skb, HW_HDR_LEN); + skb_reserve(skb, cs->hw_hdr_len); } bcs->hw.bas->goodbytes += skb->len; dobytes = TRANSBUFSIZE - skb->len; @@ -881,14 +882,14 @@ static inline void trans_receive(unsigned char *src, unsigned count, if (dobytes == 0) { dump_bytes(DEBUG_STREAM_DUMP, "rcv data", skb->data, skb->len); - gigaset_rcv_skb(skb, bcs->cs, bcs); - bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN); + gigaset_skb_rcvd(bcs, skb); + bcs->skb = skb = + dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); if (!skb) { - dev_err(bcs->cs->dev, - "could not allocate skb\n"); + dev_err(cs->dev, "could not allocate skb\n"); return; } - skb_reserve(bcs->skb, HW_HDR_LEN); + skb_reserve(skb, cs->hw_hdr_len); dobytes = TRANSBUFSIZE; } } @@ -897,7 +898,7 @@ static inline void trans_receive(unsigned char *src, unsigned count, void gigaset_isoc_receive(unsigned char *src, unsigned count, struct bc_state *bcs) { switch (bcs->proto2) { - case ISDN_PROTO_L2_HDLC: + case L2_HDLC: hdlc_unpack(src, count, bcs); break; default: /* assume transparent */ @@ -981,8 +982,10 @@ void gigaset_isoc_input(struct inbuf_t *inbuf) * @bcs: B channel descriptor structure. * @skb: data to send. * - * Called by i4l.c to queue an skb for sending, and start transmission if + * Called by LL to 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, -- cgit v1.2.2 From aaba2b3f8213e1d66e71c351fa7a2b1cbd974d3c Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Tue, 6 Oct 2009 12:19:12 +0000 Subject: gigaset: allow building without I4L Add a dummy LL interface to the Gigaset driver so that it can be built and, in a limited way, used without the ISDN4Linux subsystem. Impact: new configuration alternative Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/Kconfig | 13 +++++++- drivers/isdn/gigaset/Makefile | 4 ++- drivers/isdn/gigaset/dummyll.c | 68 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 drivers/isdn/gigaset/dummyll.c (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/Kconfig b/drivers/isdn/gigaset/Kconfig index 18ab8652aa57..6fd2dc1e97fb 100644 --- a/drivers/isdn/gigaset/Kconfig +++ b/drivers/isdn/gigaset/Kconfig @@ -1,6 +1,5 @@ menuconfig ISDN_DRV_GIGASET tristate "Siemens Gigaset support" - depends on ISDN_I4L select CRC_CCITT select BITREVERSE help @@ -11,9 +10,21 @@ menuconfig ISDN_DRV_GIGASET If you have one of these devices, say M here and for at least one of the connection specific parts that follow. This will build a module called "gigaset". + Note: If you build the ISDN4Linux subsystem (ISDN_I4L) + as a module, you have to build this driver as a module too, + otherwise the Gigaset device won't show up as an ISDN device. if ISDN_DRV_GIGASET +config GIGASET_I4L + bool + depends on ISDN_I4L='y'||(ISDN_I4L='m'&&ISDN_DRV_GIGASET='m') + default y + +config GIGASET_DUMMYLL + bool + default !GIGASET_I4L + config GIGASET_BASE tristate "Gigaset base station support" depends on USB diff --git a/drivers/isdn/gigaset/Makefile b/drivers/isdn/gigaset/Makefile index e9d3189f56b7..d429202ba8ef 100644 --- a/drivers/isdn/gigaset/Makefile +++ b/drivers/isdn/gigaset/Makefile @@ -1,4 +1,6 @@ -gigaset-y := common.o interface.o proc.o ev-layer.o i4l.o asyncdata.o +gigaset-y := common.o interface.o proc.o ev-layer.o asyncdata.o +gigaset-$(CONFIG_GIGASET_I4L) += i4l.o +gigaset-$(CONFIG_GIGASET_DUMMYLL) += dummyll.o usb_gigaset-y := usb-gigaset.o ser_gigaset-y := ser-gigaset.o bas_gigaset-y := bas-gigaset.o isocdata.o diff --git a/drivers/isdn/gigaset/dummyll.c b/drivers/isdn/gigaset/dummyll.c new file mode 100644 index 000000000000..5b27c996af6d --- /dev/null +++ b/drivers/isdn/gigaset/dummyll.c @@ -0,0 +1,68 @@ +/* + * Dummy LL interface for the Gigaset driver + * + * Copyright (c) 2009 by Tilman Schmidt . + * + * ===================================================================== + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * ===================================================================== + */ + +#include "gigaset.h" + +void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) +{ +} +EXPORT_SYMBOL_GPL(gigaset_skb_sent); + +void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb) +{ +} +EXPORT_SYMBOL_GPL(gigaset_skb_rcvd); + +void gigaset_isdn_rcv_err(struct bc_state *bcs) +{ +} +EXPORT_SYMBOL_GPL(gigaset_isdn_rcv_err); + +int gigaset_isdn_icall(struct at_state_t *at_state) +{ + return ICALL_IGNORE; +} + +void gigaset_isdn_connD(struct bc_state *bcs) +{ +} + +void gigaset_isdn_hupD(struct bc_state *bcs) +{ +} + +void gigaset_isdn_connB(struct bc_state *bcs) +{ +} + +void gigaset_isdn_hupB(struct bc_state *bcs) +{ +} + +void gigaset_isdn_start(struct cardstate *cs) +{ +} + +void gigaset_isdn_stop(struct cardstate *cs) +{ +} + +int gigaset_isdn_register(struct cardstate *cs, const char *isdnid) +{ + pr_info("no ISDN subsystem interface\n"); + return 1; +} + +void gigaset_isdn_unregister(struct cardstate *cs) +{ +} -- cgit v1.2.2 From 7bb5fdc2fb021e32703ed1ff0269876bde1fa962 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Tue, 6 Oct 2009 12:19:17 +0000 Subject: gigaset: add Kernel CAPI interface (v3) Add a Kernel CAPI interface to the Gigaset driver. Impact: optional new functionality Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/Kconfig | 18 +- drivers/isdn/gigaset/Makefile | 1 + drivers/isdn/gigaset/capi.c | 2273 +++++++++++++++++++++++++++++++++++++++ drivers/isdn/gigaset/common.c | 26 + drivers/isdn/gigaset/ev-layer.c | 26 +- drivers/isdn/gigaset/gigaset.h | 7 +- 6 files changed, 2335 insertions(+), 16 deletions(-) create mode 100644 drivers/isdn/gigaset/capi.c (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/Kconfig b/drivers/isdn/gigaset/Kconfig index 6fd2dc1e97fb..dcefedc7044a 100644 --- a/drivers/isdn/gigaset/Kconfig +++ b/drivers/isdn/gigaset/Kconfig @@ -10,20 +10,32 @@ menuconfig ISDN_DRV_GIGASET If you have one of these devices, say M here and for at least one of the connection specific parts that follow. This will build a module called "gigaset". - Note: If you build the ISDN4Linux subsystem (ISDN_I4L) + Note: If you build your ISDN subsystem (ISDN_CAPI or ISDN_I4L) as a module, you have to build this driver as a module too, otherwise the Gigaset device won't show up as an ISDN device. if ISDN_DRV_GIGASET +config GIGASET_CAPI + bool "Gigaset CAPI support (EXPERIMENTAL)" + depends on EXPERIMENTAL + depends on ISDN_CAPI='y'||(ISDN_CAPI='m'&&ISDN_DRV_GIGASET='m') + default ISDN_I4L='n' + help + Build the Gigaset driver as a CAPI 2.0 driver interfacing with + the Kernel CAPI subsystem. To use it with the old ISDN4Linux + subsystem you'll have to enable the capidrv glue driver. + (select ISDN_CAPI_CAPIDRV.) + Say N to build the old native ISDN4Linux variant. + config GIGASET_I4L bool depends on ISDN_I4L='y'||(ISDN_I4L='m'&&ISDN_DRV_GIGASET='m') - default y + default !GIGASET_CAPI config GIGASET_DUMMYLL bool - default !GIGASET_I4L + default !GIGASET_CAPI&&!GIGASET_I4L config GIGASET_BASE tristate "Gigaset base station support" diff --git a/drivers/isdn/gigaset/Makefile b/drivers/isdn/gigaset/Makefile index d429202ba8ef..c453b72272a0 100644 --- a/drivers/isdn/gigaset/Makefile +++ b/drivers/isdn/gigaset/Makefile @@ -1,4 +1,5 @@ gigaset-y := common.o interface.o proc.o ev-layer.o asyncdata.o +gigaset-$(CONFIG_GIGASET_CAPI) += capi.o gigaset-$(CONFIG_GIGASET_I4L) += i4l.o gigaset-$(CONFIG_GIGASET_DUMMYLL) += dummyll.o usb_gigaset-y := usb-gigaset.o diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c new file mode 100644 index 000000000000..c276a925b36f --- /dev/null +++ b/drivers/isdn/gigaset/capi.c @@ -0,0 +1,2273 @@ +/* + * Kernel CAPI interface for the Gigaset driver + * + * Copyright (c) 2009 by Tilman Schmidt . + * + * ===================================================================== + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * ===================================================================== + */ + +#include "gigaset.h" +#include +#include +#include +#include + +/* missing from kernelcapi.h */ +#define CapiNcpiNotSupportedByProtocol 0x0001 +#define CapiFlagsNotSupportedByProtocol 0x0002 +#define CapiAlertAlreadySent 0x0003 +#define CapiFacilitySpecificFunctionNotSupported 0x3011 + +/* missing from capicmd.h */ +#define CAPI_CONNECT_IND_BASELEN (CAPI_MSG_BASELEN+4+2+8*1) +#define CAPI_CONNECT_ACTIVE_IND_BASELEN (CAPI_MSG_BASELEN+4+3*1) +#define CAPI_CONNECT_B3_IND_BASELEN (CAPI_MSG_BASELEN+4+1) +#define CAPI_CONNECT_B3_ACTIVE_IND_BASELEN (CAPI_MSG_BASELEN+4+1) +#define CAPI_DATA_B3_REQ_LEN64 (CAPI_MSG_BASELEN+4+4+2+2+2+8) +#define CAPI_DATA_B3_CONF_LEN (CAPI_MSG_BASELEN+4+2+2) +#define CAPI_DISCONNECT_IND_LEN (CAPI_MSG_BASELEN+4+2) +#define CAPI_DISCONNECT_B3_IND_BASELEN (CAPI_MSG_BASELEN+4+2+1) +#define CAPI_FACILITY_CONF_BASELEN (CAPI_MSG_BASELEN+4+2+2+1) +/* most _CONF messages contain only Controller/PLCI/NCCI and Info parameters */ +#define CAPI_STDCONF_LEN (CAPI_MSG_BASELEN+4+2) + +#define CAPI_FACILITY_HANDSET 0x0000 +#define CAPI_FACILITY_DTMF 0x0001 +#define CAPI_FACILITY_V42BIS 0x0002 +#define CAPI_FACILITY_SUPPSVC 0x0003 +#define CAPI_FACILITY_WAKEUP 0x0004 +#define CAPI_FACILITY_LI 0x0005 + +#define CAPI_SUPPSVC_GETSUPPORTED 0x0000 + +/* missing from capiutil.h */ +#define CAPIMSG_PLCI_PART(m) CAPIMSG_U8(m, 9) +#define CAPIMSG_NCCI_PART(m) CAPIMSG_U16(m, 10) +#define CAPIMSG_HANDLE_REQ(m) CAPIMSG_U16(m, 18) /* DATA_B3_REQ/_IND only! */ +#define CAPIMSG_FLAGS(m) CAPIMSG_U16(m, 20) +#define CAPIMSG_SETCONTROLLER(m, contr) capimsg_setu8(m, 8, contr) +#define CAPIMSG_SETPLCI_PART(m, plci) capimsg_setu8(m, 9, plci) +#define CAPIMSG_SETNCCI_PART(m, ncci) capimsg_setu16(m, 10, ncci) +#define CAPIMSG_SETFLAGS(m, flags) capimsg_setu16(m, 20, flags) + +/* parameters with differing location in DATA_B3_CONF/_RESP: */ +#define CAPIMSG_SETHANDLE_CONF(m, handle) capimsg_setu16(m, 12, handle) +#define CAPIMSG_SETINFO_CONF(m, info) capimsg_setu16(m, 14, info) + +/* Flags (DATA_B3_REQ/_IND) */ +#define CAPI_FLAGS_DELIVERY_CONFIRMATION 0x04 +#define CAPI_FLAGS_RESERVED (~0x1f) + +/* buffer sizes */ +#define MAX_BC_OCTETS 11 +#define MAX_HLC_OCTETS 3 +#define MAX_NUMBER_DIGITS 20 +#define MAX_FMT_IE_LEN 20 + +/* values for gigaset_capi_appl.connected */ +#define APCONN_NONE 0 /* inactive/listening */ +#define APCONN_SETUP 1 /* connecting */ +#define APCONN_ACTIVE 2 /* B channel up */ + +/* registered application data structure */ +struct gigaset_capi_appl { + struct list_head ctrlist; + struct gigaset_capi_appl *bcnext; + u16 id; + u16 nextMessageNumber; + u32 listenInfoMask; + u32 listenCIPmask; + int connected; +}; + +/* CAPI specific controller data structure */ +struct gigaset_capi_ctr { + struct capi_ctr ctr; + struct list_head appls; + struct sk_buff_head sendqueue; + atomic_t sendqlen; + /* two _cmsg structures possibly used concurrently: */ + _cmsg hcmsg; /* for message composition triggered from hardware */ + _cmsg acmsg; /* for dissection of messages sent from application */ + u8 bc_buf[MAX_BC_OCTETS+1]; + u8 hlc_buf[MAX_HLC_OCTETS+1]; + u8 cgpty_buf[MAX_NUMBER_DIGITS+3]; + u8 cdpty_buf[MAX_NUMBER_DIGITS+2]; +}; + +/* CIP Value table (from CAPI 2.0 standard, ch. 6.1) */ +static struct { + u8 *bc; + u8 *hlc; +} cip2bchlc[] = { + [1] = { "8090A3", NULL }, + /* Speech (A-law) */ + [2] = { "8890", NULL }, + /* Unrestricted digital information */ + [3] = { "8990", NULL }, + /* Restricted digital information */ + [4] = { "9090A3", NULL }, + /* 3,1 kHz audio (A-law) */ + [5] = { "9190", NULL }, + /* 7 kHz audio */ + [6] = { "9890", NULL }, + /* Video */ + [7] = { "88C0C6E6", NULL }, + /* Packet mode */ + [8] = { "8890218F", NULL }, + /* 56 kbit/s rate adaptation */ + [9] = { "9190A5", NULL }, + /* Unrestricted digital information with tones/announcements */ + [16] = { "8090A3", "9181" }, + /* Telephony */ + [17] = { "9090A3", "9184" }, + /* Group 2/3 facsimile */ + [18] = { "8890", "91A1" }, + /* Group 4 facsimile Class 1 */ + [19] = { "8890", "91A4" }, + /* Teletex service basic and mixed mode + and Group 4 facsimile service Classes II and III */ + [20] = { "8890", "91A8" }, + /* Teletex service basic and processable mode */ + [21] = { "8890", "91B1" }, + /* Teletex service basic mode */ + [22] = { "8890", "91B2" }, + /* International interworking for Videotex */ + [23] = { "8890", "91B5" }, + /* Telex */ + [24] = { "8890", "91B8" }, + /* Message Handling Systems in accordance with X.400 */ + [25] = { "8890", "91C1" }, + /* OSI application in accordance with X.200 */ + [26] = { "9190A5", "9181" }, + /* 7 kHz telephony */ + [27] = { "9190A5", "916001" }, + /* Video telephony, first connection */ + [28] = { "8890", "916002" }, + /* Video telephony, second connection */ +}; + +/* + * helper functions + * ================ + */ + +/* + * emit unsupported parameter warning + */ +static inline void ignore_cstruct_param(struct cardstate *cs, _cstruct param, + char *msgname, char *paramname) +{ + if (param && *param) + dev_warn(cs->dev, "%s: ignoring unsupported parameter: %s\n", + msgname, paramname); +} + +static inline void ignore_cmstruct_param(struct cardstate *cs, _cmstruct param, + char *msgname, char *paramname) +{ + if (param != CAPI_DEFAULT) + dev_warn(cs->dev, "%s: ignoring unsupported parameter: %s\n", + msgname, paramname); +} + +/* + * check for legal hex digit + */ +static inline int ishexdigit(char c) +{ + if (c >= '0' && c <= '9') + return 1; + if (c >= 'A' && c <= 'F') + return 1; + if (c >= 'a' && c <= 'f') + return 1; + return 0; +} + +/* + * convert hex to binary + */ +static inline u8 hex2bin(char c) +{ + int result = c & 0x0f; + if (c & 0x40) + result += 9; + return result; +} + +/* + * convert an IE from Gigaset hex string to ETSI binary representation + * including length byte + * return value: result length, -1 on error + */ +static int encode_ie(char *in, u8 *out, int maxlen) +{ + int l = 0; + while (*in) { + if (!ishexdigit(in[0]) || !ishexdigit(in[1]) || l >= maxlen) + return -1; + out[++l] = (hex2bin(in[0]) << 4) + hex2bin(in[1]); + in += 2; + } + out[0] = l; + return l; +} + +/* + * convert an IE from ETSI binary representation including length byte + * to Gigaset hex string + */ +static void decode_ie(u8 *in, char *out) +{ + int i = *in; + while (i-- > 0) { + /* ToDo: conversion to upper case necessary? */ + *out++ = toupper(hex_asc_hi(*++in)); + *out++ = toupper(hex_asc_lo(*in)); + } +} + +/* + * retrieve application data structure for an application ID + */ +static inline struct gigaset_capi_appl * +get_appl(struct gigaset_capi_ctr *iif, u16 appl) +{ + struct gigaset_capi_appl *ap; + + list_for_each_entry(ap, &iif->appls, ctrlist) + if (ap->id == appl) + return ap; + return NULL; +} + +/* + * dump CAPI message to kernel messages for debugging + */ +static inline void dump_cmsg(enum debuglevel level, const char *tag, _cmsg *p) +{ +#ifdef CONFIG_GIGASET_DEBUG + _cdebbuf *cdb; + + if (!(gigaset_debuglevel & level)) + return; + + cdb = capi_cmsg2str(p); + if (cdb) { + gig_dbg(level, "%s: [%d] %s", tag, p->ApplId, cdb->buf); + cdebbuf_free(cdb); + } else { + gig_dbg(level, "%s: [%d] %s", tag, p->ApplId, + capi_cmd2str(p->Command, p->Subcommand)); + } +#endif +} + +static inline void dump_rawmsg(enum debuglevel level, const char *tag, + unsigned char *data) +{ +#ifdef CONFIG_GIGASET_DEBUG + char *dbgline; + int i, l; + + if (!(gigaset_debuglevel & level)) + return; + + l = CAPIMSG_LEN(data); + if (l < 12) { + gig_dbg(level, "%s: ??? LEN=%04d", tag, l); + return; + } + gig_dbg(level, "%s: 0x%02x:0x%02x: ID=%03d #0x%04x LEN=%04d NCCI=0x%x", + tag, CAPIMSG_COMMAND(data), CAPIMSG_SUBCOMMAND(data), + CAPIMSG_APPID(data), CAPIMSG_MSGID(data), l, + CAPIMSG_CONTROL(data)); + l -= 12; + dbgline = kmalloc(3*l, GFP_ATOMIC); + if (!dbgline) + return; + for (i = 0; i < l; i++) { + dbgline[3*i] = hex_asc_hi(data[12+i]); + dbgline[3*i+1] = hex_asc_lo(data[12+i]); + dbgline[3*i+2] = ' '; + } + dbgline[3*l-1] = '\0'; + gig_dbg(level, " %s", dbgline); + kfree(dbgline); + if (CAPIMSG_COMMAND(data) == CAPI_DATA_B3 && + (CAPIMSG_SUBCOMMAND(data) == CAPI_REQ || + CAPIMSG_SUBCOMMAND(data) == CAPI_IND) && + CAPIMSG_DATALEN(data) > 0) { + l = CAPIMSG_DATALEN(data); + dbgline = kmalloc(3*l, GFP_ATOMIC); + if (!dbgline) + return; + data += CAPIMSG_LEN(data); + for (i = 0; i < l; i++) { + dbgline[3*i] = hex_asc_hi(data[i]); + dbgline[3*i+1] = hex_asc_lo(data[i]); + dbgline[3*i+2] = ' '; + } + dbgline[3*l-1] = '\0'; + gig_dbg(level, " %s", dbgline); + kfree(dbgline); + } +#endif +} + +/* + * format CAPI IE as string + */ + +static const char *format_ie(const char *ie) +{ + static char result[3*MAX_FMT_IE_LEN]; + int len, count; + char *pout = result; + + if (!ie) + return "NULL"; + + count = len = ie[0]; + if (count > MAX_FMT_IE_LEN) + count = MAX_FMT_IE_LEN-1; + while (count--) { + *pout++ = hex_asc_hi(*++ie); + *pout++ = hex_asc_lo(*ie); + *pout++ = ' '; + } + if (len > MAX_FMT_IE_LEN) { + *pout++ = '.'; + *pout++ = '.'; + *pout++ = '.'; + } + *--pout = 0; + return result; +} + + +/* + * driver interface functions + * ========================== + */ + +/** + * gigaset_skb_sent() - acknowledge transmission of outgoing skb + * @bcs: B channel descriptor structure. + * @skb: sent data. + * + * Called by hardware module {bas,ser,usb}_gigaset when the data in a + * skb has been successfully sent, for signalling completion to the LL. + */ +void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb) +{ + struct cardstate *cs = bcs->cs; + struct gigaset_capi_ctr *iif = cs->iif; + struct gigaset_capi_appl *ap = bcs->ap; + struct sk_buff *cskb; + u16 flags; + + /* update statistics */ + ++bcs->trans_up; + + if (!ap) { + dev_err(cs->dev, "%s: no application\n", __func__); + return; + } + + /* don't send further B3 messages if disconnected */ + if (ap->connected < APCONN_ACTIVE) { + gig_dbg(DEBUG_LLDATA, "disconnected, discarding ack"); + return; + } + + /* ToDo: honor unset "delivery confirmation" bit */ + flags = CAPIMSG_FLAGS(dskb->head); + + /* build DATA_B3_CONF message */ + cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC); + if (!cskb) { + dev_err(cs->dev, "%s: out of memory\n", __func__); + return; + } + /* frequent message, avoid _cmsg overhead */ + CAPIMSG_SETLEN(cskb->data, CAPI_DATA_B3_CONF_LEN); + CAPIMSG_SETAPPID(cskb->data, ap->id); + CAPIMSG_SETCOMMAND(cskb->data, CAPI_DATA_B3); + CAPIMSG_SETSUBCOMMAND(cskb->data, CAPI_CONF); + CAPIMSG_SETMSGID(cskb->data, CAPIMSG_MSGID(dskb->head)); + CAPIMSG_SETCONTROLLER(cskb->data, iif->ctr.cnr); + CAPIMSG_SETPLCI_PART(cskb->data, bcs->channel + 1); + CAPIMSG_SETNCCI_PART(cskb->data, 1); + CAPIMSG_SETHANDLE_CONF(cskb->data, CAPIMSG_HANDLE_REQ(dskb->head)); + if (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION) + CAPIMSG_SETINFO_CONF(cskb->data, + CapiFlagsNotSupportedByProtocol); + else + CAPIMSG_SETINFO_CONF(cskb->data, CAPI_NOERROR); + + /* emit message */ + dump_rawmsg(DEBUG_LLDATA, "DATA_B3_CONF", cskb->data); + capi_ctr_handle_message(&iif->ctr, ap->id, cskb); +} +EXPORT_SYMBOL_GPL(gigaset_skb_sent); + +/** + * gigaset_skb_rcvd() - pass received skb to LL + * @bcs: B channel descriptor structure. + * @skb: received data. + * + * Called by hardware module {bas,ser,usb}_gigaset when user data has + * been successfully received, for passing to the LL. + * Warning: skb must not be accessed anymore! + */ +void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb) +{ + struct cardstate *cs = bcs->cs; + struct gigaset_capi_ctr *iif = cs->iif; + struct gigaset_capi_appl *ap = bcs->ap; + int len = skb->len; + + /* update statistics */ + bcs->trans_down++; + + if (!ap) { + dev_err(cs->dev, "%s: no application\n", __func__); + return; + } + + /* don't send further B3 messages if disconnected */ + if (ap->connected < APCONN_ACTIVE) { + gig_dbg(DEBUG_LLDATA, "disconnected, discarding data"); + dev_kfree_skb(skb); + return; + } + + /* + * prepend DATA_B3_IND message to payload + * Parameters: NCCI = 1, all others 0/unused + * frequent message, avoid _cmsg overhead + */ + skb_push(skb, CAPI_DATA_B3_REQ_LEN); + CAPIMSG_SETLEN(skb->data, CAPI_DATA_B3_REQ_LEN); + CAPIMSG_SETAPPID(skb->data, ap->id); + CAPIMSG_SETCOMMAND(skb->data, CAPI_DATA_B3); + CAPIMSG_SETSUBCOMMAND(skb->data, CAPI_IND); + CAPIMSG_SETMSGID(skb->data, ap->nextMessageNumber++); + CAPIMSG_SETCONTROLLER(skb->data, iif->ctr.cnr); + CAPIMSG_SETPLCI_PART(skb->data, bcs->channel + 1); + CAPIMSG_SETNCCI_PART(skb->data, 1); + /* Data parameter not used */ + CAPIMSG_SETDATALEN(skb->data, len); + /* Data handle parameter not used */ + CAPIMSG_SETFLAGS(skb->data, 0); + /* Data64 parameter not present */ + + /* emit message */ + dump_rawmsg(DEBUG_LLDATA, "DATA_B3_IND", skb->data); + capi_ctr_handle_message(&iif->ctr, ap->id, skb); +} +EXPORT_SYMBOL_GPL(gigaset_skb_rcvd); + +/** + * gigaset_isdn_rcv_err() - signal receive error + * @bcs: B channel descriptor structure. + * + * Called by hardware module {bas,ser,usb}_gigaset when a receive error + * has occurred, for signalling to the LL. + */ +void gigaset_isdn_rcv_err(struct bc_state *bcs) +{ + /* if currently ignoring packets, just count down */ + if (bcs->ignore) { + bcs->ignore--; + return; + } + + /* update statistics */ + bcs->corrupted++; + + /* ToDo: signal error -> LL */ +} +EXPORT_SYMBOL_GPL(gigaset_isdn_rcv_err); + +/** + * gigaset_isdn_icall() - signal incoming call + * @at_state: connection state structure. + * + * Called by main module at tasklet level to notify the LL that an incoming + * call has been received. @at_state contains the parameters of the call. + * + * Return value: call disposition (ICALL_*) + */ +int gigaset_isdn_icall(struct at_state_t *at_state) +{ + struct cardstate *cs = at_state->cs; + struct bc_state *bcs = at_state->bcs; + struct gigaset_capi_ctr *iif = cs->iif; + struct gigaset_capi_appl *ap; + u32 actCIPmask; + struct sk_buff *skb; + unsigned int msgsize; + int i; + + /* + * ToDo: signal calls without a free B channel, too + * (requires a u8 handle for the at_state structure that can + * be stored in the PLCI and used in the CONNECT_RESP message + * handler to retrieve it) + */ + if (!bcs) + return ICALL_IGNORE; + + /* prepare CONNECT_IND message, using B channel number as PLCI */ + capi_cmsg_header(&iif->hcmsg, 0, CAPI_CONNECT, CAPI_IND, 0, + iif->ctr.cnr | ((bcs->channel + 1) << 8)); + + /* minimum size, all structs empty */ + msgsize = CAPI_CONNECT_IND_BASELEN; + + /* Bearer Capability (mandatory) */ + if (at_state->str_var[STR_ZBC]) { + /* pass on BC from Gigaset */ + if (encode_ie(at_state->str_var[STR_ZBC], iif->bc_buf, + MAX_BC_OCTETS) < 0) { + dev_warn(cs->dev, "RING ignored - bad BC %s\n", + at_state->str_var[STR_ZBC]); + return ICALL_IGNORE; + } + + /* look up corresponding CIP value */ + iif->hcmsg.CIPValue = 0; /* default if nothing found */ + for (i = 0; i < ARRAY_SIZE(cip2bchlc); i++) + if (cip2bchlc[i].bc != NULL && + cip2bchlc[i].hlc == NULL && + !strcmp(cip2bchlc[i].bc, + at_state->str_var[STR_ZBC])) { + iif->hcmsg.CIPValue = i; + break; + } + } else { + /* no BC (internal call): assume CIP 1 (speech, A-law) */ + iif->hcmsg.CIPValue = 1; + encode_ie(cip2bchlc[1].bc, iif->bc_buf, MAX_BC_OCTETS); + } + iif->hcmsg.BC = iif->bc_buf; + msgsize += iif->hcmsg.BC[0]; + + /* High Layer Compatibility (optional) */ + if (at_state->str_var[STR_ZHLC]) { + /* pass on HLC from Gigaset */ + if (encode_ie(at_state->str_var[STR_ZHLC], iif->hlc_buf, + MAX_HLC_OCTETS) < 0) { + dev_warn(cs->dev, "RING ignored - bad HLC %s\n", + at_state->str_var[STR_ZHLC]); + return ICALL_IGNORE; + } + iif->hcmsg.HLC = iif->hlc_buf; + msgsize += iif->hcmsg.HLC[0]; + + /* look up corresponding CIP value */ + /* keep BC based CIP value if none found */ + if (at_state->str_var[STR_ZBC]) + for (i = 0; i < ARRAY_SIZE(cip2bchlc); i++) + if (cip2bchlc[i].hlc != NULL && + !strcmp(cip2bchlc[i].hlc, + at_state->str_var[STR_ZHLC]) && + !strcmp(cip2bchlc[i].bc, + at_state->str_var[STR_ZBC])) { + iif->hcmsg.CIPValue = i; + break; + } + } + + /* Called Party Number (optional) */ + if (at_state->str_var[STR_ZCPN]) { + i = strlen(at_state->str_var[STR_ZCPN]); + if (i > MAX_NUMBER_DIGITS) { + dev_warn(cs->dev, "RING ignored - bad number %s\n", + at_state->str_var[STR_ZBC]); + return ICALL_IGNORE; + } + iif->cdpty_buf[0] = i + 1; + iif->cdpty_buf[1] = 0x80; /* type / numbering plan unknown */ + memcpy(iif->cdpty_buf+2, at_state->str_var[STR_ZCPN], i); + iif->hcmsg.CalledPartyNumber = iif->cdpty_buf; + msgsize += iif->hcmsg.CalledPartyNumber[0]; + } + + /* Calling Party Number (optional) */ + if (at_state->str_var[STR_NMBR]) { + i = strlen(at_state->str_var[STR_NMBR]); + if (i > MAX_NUMBER_DIGITS) { + dev_warn(cs->dev, "RING ignored - bad number %s\n", + at_state->str_var[STR_ZBC]); + return ICALL_IGNORE; + } + iif->cgpty_buf[0] = i + 2; + iif->cgpty_buf[1] = 0x00; /* type / numbering plan unknown */ + iif->cgpty_buf[2] = 0x80; /* pres. allowed, not screened */ + memcpy(iif->cgpty_buf+3, at_state->str_var[STR_NMBR], i); + iif->hcmsg.CallingPartyNumber = iif->cgpty_buf; + msgsize += iif->hcmsg.CallingPartyNumber[0]; + } + + /* remaining parameters (not supported, always left NULL): + * - CalledPartySubaddress + * - CallingPartySubaddress + * - AdditionalInfo + * - BChannelinformation + * - Keypadfacility + * - Useruserdata + * - Facilitydataarray + */ + + gig_dbg(DEBUG_CMD, "icall: PLCI %x CIP %d BC %s", + iif->hcmsg.adr.adrPLCI, iif->hcmsg.CIPValue, + format_ie(iif->hcmsg.BC)); + gig_dbg(DEBUG_CMD, "icall: HLC %s", + format_ie(iif->hcmsg.HLC)); + gig_dbg(DEBUG_CMD, "icall: CgPty %s", + format_ie(iif->hcmsg.CallingPartyNumber)); + gig_dbg(DEBUG_CMD, "icall: CdPty %s", + format_ie(iif->hcmsg.CalledPartyNumber)); + + /* scan application list for matching listeners */ + bcs->ap = NULL; + actCIPmask = 1 | (1 << iif->hcmsg.CIPValue); + list_for_each_entry(ap, &iif->appls, ctrlist) + if (actCIPmask & ap->listenCIPmask) { + /* build CONNECT_IND message for this application */ + iif->hcmsg.ApplId = ap->id; + iif->hcmsg.Messagenumber = ap->nextMessageNumber++; + + skb = alloc_skb(msgsize, GFP_ATOMIC); + if (!skb) { + dev_err(cs->dev, "%s: out of memory\n", + __func__); + break; + } + capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize)); + dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); + + /* add to listeners on this B channel, update state */ + ap->bcnext = bcs->ap; + bcs->ap = ap; + bcs->chstate |= CHS_NOTIFY_LL; + ap->connected = APCONN_SETUP; + + /* emit message */ + capi_ctr_handle_message(&iif->ctr, ap->id, skb); + } + + /* + * Return "accept" if any listeners. + * Gigaset will send ALERTING. + * There doesn't seem to be a way to avoid this. + */ + return bcs->ap ? ICALL_ACCEPT : ICALL_IGNORE; +} + +/* + * send a DISCONNECT_IND message to an application + * does not sleep, clobbers the controller's hcmsg structure + */ +static void send_disconnect_ind(struct bc_state *bcs, + struct gigaset_capi_appl *ap, u16 reason) +{ + struct cardstate *cs = bcs->cs; + struct gigaset_capi_ctr *iif = cs->iif; + struct sk_buff *skb; + + if (ap->connected == APCONN_NONE) + return; + + capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT, CAPI_IND, + ap->nextMessageNumber++, + iif->ctr.cnr | ((bcs->channel + 1) << 8)); + iif->hcmsg.Reason = reason; + skb = alloc_skb(CAPI_DISCONNECT_IND_LEN, GFP_ATOMIC); + if (!skb) { + dev_err(cs->dev, "%s: out of memory\n", __func__); + return; + } + capi_cmsg2message(&iif->hcmsg, __skb_put(skb, CAPI_DISCONNECT_IND_LEN)); + dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); + ap->connected = APCONN_NONE; + capi_ctr_handle_message(&iif->ctr, ap->id, skb); +} + +/* + * send a DISCONNECT_B3_IND message to an application + * Parameters: NCCI = 1, NCPI empty, Reason_B3 = 0 + * does not sleep, clobbers the controller's hcmsg structure + */ +static void send_disconnect_b3_ind(struct bc_state *bcs, + struct gigaset_capi_appl *ap) +{ + struct cardstate *cs = bcs->cs; + struct gigaset_capi_ctr *iif = cs->iif; + struct sk_buff *skb; + + /* nothing to do if no logical connection active */ + if (ap->connected < APCONN_ACTIVE) + return; + ap->connected = APCONN_SETUP; + + capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND, + ap->nextMessageNumber++, + iif->ctr.cnr | ((bcs->channel + 1) << 8) | (1 << 16)); + skb = alloc_skb(CAPI_DISCONNECT_B3_IND_BASELEN, GFP_ATOMIC); + if (!skb) { + dev_err(cs->dev, "%s: out of memory\n", __func__); + return; + } + capi_cmsg2message(&iif->hcmsg, + __skb_put(skb, CAPI_DISCONNECT_B3_IND_BASELEN)); + dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); + capi_ctr_handle_message(&iif->ctr, ap->id, skb); +} + +/** + * gigaset_isdn_connD() - signal D channel connect + * @bcs: B channel descriptor structure. + * + * Called by main module at tasklet level to notify the LL that the D channel + * connection has been established. + */ +void gigaset_isdn_connD(struct bc_state *bcs) +{ + struct cardstate *cs = bcs->cs; + struct gigaset_capi_ctr *iif = cs->iif; + struct gigaset_capi_appl *ap = bcs->ap; + struct sk_buff *skb; + unsigned int msgsize; + + if (!ap) { + dev_err(cs->dev, "%s: no application\n", __func__); + return; + } + while (ap->bcnext) { + /* this should never happen */ + dev_warn(cs->dev, "%s: dropping extra application %u\n", + __func__, ap->bcnext->id); + send_disconnect_ind(bcs, ap->bcnext, + CapiCallGivenToOtherApplication); + ap->bcnext = ap->bcnext->bcnext; + } + if (ap->connected == APCONN_NONE) { + dev_warn(cs->dev, "%s: application %u not connected\n", + __func__, ap->id); + return; + } + + /* prepare CONNECT_ACTIVE_IND message + * Note: LLC not supported by device + */ + capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_CONNECT_ACTIVE, CAPI_IND, + ap->nextMessageNumber++, + iif->ctr.cnr | ((bcs->channel + 1) << 8)); + + /* minimum size, all structs empty */ + msgsize = CAPI_CONNECT_ACTIVE_IND_BASELEN; + + /* ToDo: set parameter: Connected number + * (requires ev-layer state machine extension to collect + * ZCON device reply) + */ + + /* build and emit CONNECT_ACTIVE_IND message */ + skb = alloc_skb(msgsize, GFP_ATOMIC); + if (!skb) { + dev_err(cs->dev, "%s: out of memory\n", __func__); + return; + } + capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize)); + dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); + capi_ctr_handle_message(&iif->ctr, ap->id, skb); +} + +/** + * gigaset_isdn_hupD() - signal D channel hangup + * @bcs: B channel descriptor structure. + * + * Called by main module at tasklet level to notify the LL that the D channel + * connection has been shut down. + */ +void gigaset_isdn_hupD(struct bc_state *bcs) +{ + struct gigaset_capi_appl *ap; + + /* + * ToDo: pass on reason code reported by device + * (requires ev-layer state machine extension to collect + * ZCAU device reply) + */ + for (ap = bcs->ap; ap != NULL; ap = ap->bcnext) { + send_disconnect_b3_ind(bcs, ap); + send_disconnect_ind(bcs, ap, 0); + } + bcs->ap = NULL; +} + +/** + * gigaset_isdn_connB() - signal B channel connect + * @bcs: B channel descriptor structure. + * + * Called by main module at tasklet level to notify the LL that the B channel + * connection has been established. + */ +void gigaset_isdn_connB(struct bc_state *bcs) +{ + struct cardstate *cs = bcs->cs; + struct gigaset_capi_ctr *iif = cs->iif; + struct gigaset_capi_appl *ap = bcs->ap; + struct sk_buff *skb; + unsigned int msgsize; + u8 command; + + if (!ap) { + dev_err(cs->dev, "%s: no application\n", __func__); + return; + } + while (ap->bcnext) { + /* this should never happen */ + dev_warn(cs->dev, "%s: dropping extra application %u\n", + __func__, ap->bcnext->id); + send_disconnect_ind(bcs, ap->bcnext, + CapiCallGivenToOtherApplication); + ap->bcnext = ap->bcnext->bcnext; + } + if (!ap->connected) { + dev_warn(cs->dev, "%s: application %u not connected\n", + __func__, ap->id); + return; + } + + /* + * emit CONNECT_B3_ACTIVE_IND if we already got CONNECT_B3_REQ; + * otherwise we have to emit CONNECT_B3_IND first, and follow up with + * CONNECT_B3_ACTIVE_IND in reply to CONNECT_B3_RESP + * Parameters in both cases always: NCCI = 1, NCPI empty + */ + if (ap->connected >= APCONN_ACTIVE) { + command = CAPI_CONNECT_B3_ACTIVE; + msgsize = CAPI_CONNECT_B3_ACTIVE_IND_BASELEN; + } else { + command = CAPI_CONNECT_B3; + msgsize = CAPI_CONNECT_B3_IND_BASELEN; + } + capi_cmsg_header(&iif->hcmsg, ap->id, command, CAPI_IND, + ap->nextMessageNumber++, + iif->ctr.cnr | ((bcs->channel + 1) << 8) | (1 << 16)); + skb = alloc_skb(msgsize, GFP_ATOMIC); + if (!skb) { + dev_err(cs->dev, "%s: out of memory\n", __func__); + return; + } + capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize)); + dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); + ap->connected = APCONN_ACTIVE; + capi_ctr_handle_message(&iif->ctr, ap->id, skb); +} + +/** + * gigaset_isdn_hupB() - signal B channel hangup + * @bcs: B channel descriptor structure. + * + * Called by main module to notify the LL that the B channel connection has + * been shut down. + */ +void gigaset_isdn_hupB(struct bc_state *bcs) +{ + struct cardstate *cs = bcs->cs; + struct gigaset_capi_appl *ap = bcs->ap; + + /* ToDo: assure order of DISCONNECT_B3_IND and DISCONNECT_IND ? */ + + if (!ap) { + dev_err(cs->dev, "%s: no application\n", __func__); + return; + } + + send_disconnect_b3_ind(bcs, ap); +} + +/** + * gigaset_isdn_start() - signal device availability + * @cs: device descriptor structure. + * + * Called by main module to notify the LL that the device is available for + * use. + */ +void gigaset_isdn_start(struct cardstate *cs) +{ + struct gigaset_capi_ctr *iif = cs->iif; + + /* fill profile data: manufacturer name */ + strcpy(iif->ctr.manu, "Siemens"); + /* CAPI and device version */ + iif->ctr.version.majorversion = 2; /* CAPI 2.0 */ + iif->ctr.version.minorversion = 0; + /* ToDo: check/assert cs->gotfwver? */ + iif->ctr.version.majormanuversion = cs->fwver[0]; + iif->ctr.version.minormanuversion = cs->fwver[1]; + /* number of B channels supported */ + iif->ctr.profile.nbchannel = cs->channels; + /* global options: internal controller, supplementary services */ + iif->ctr.profile.goptions = 0x11; + /* B1 protocols: 64 kbit/s HDLC or transparent */ + iif->ctr.profile.support1 = 0x03; + /* B2 protocols: transparent only */ + /* ToDo: X.75 SLP ? */ + iif->ctr.profile.support2 = 0x02; + /* B3 protocols: transparent only */ + iif->ctr.profile.support3 = 0x01; + /* no serial number */ + strcpy(iif->ctr.serial, "0"); + capi_ctr_ready(&iif->ctr); +} + +/** + * gigaset_isdn_stop() - signal device unavailability + * @cs: device descriptor structure. + * + * Called by main module to notify the LL that the device is no longer + * available for use. + */ +void gigaset_isdn_stop(struct cardstate *cs) +{ + struct gigaset_capi_ctr *iif = cs->iif; + capi_ctr_down(&iif->ctr); +} + +/* + * kernel CAPI callback methods + * ============================ + */ + +/* + * load firmware + */ +static int gigaset_load_firmware(struct capi_ctr *ctr, capiloaddata *data) +{ + struct cardstate *cs = ctr->driverdata; + + /* AVM specific operation, not needed for Gigaset -- ignore */ + dev_notice(cs->dev, "load_firmware ignored\n"); + + return 0; +} + +/* + * reset (deactivate) controller + */ +static void gigaset_reset_ctr(struct capi_ctr *ctr) +{ + struct cardstate *cs = ctr->driverdata; + + /* AVM specific operation, not needed for Gigaset -- ignore */ + dev_notice(cs->dev, "reset_ctr ignored\n"); +} + +/* + * register CAPI application + */ +static void gigaset_register_appl(struct capi_ctr *ctr, u16 appl, + capi_register_params *rp) +{ + struct gigaset_capi_ctr *iif + = container_of(ctr, struct gigaset_capi_ctr, ctr); + struct cardstate *cs = ctr->driverdata; + struct gigaset_capi_appl *ap; + + list_for_each_entry(ap, &iif->appls, ctrlist) + if (ap->id == appl) { + dev_notice(cs->dev, + "application %u already registered\n", appl); + return; + } + + ap = kzalloc(sizeof(*ap), GFP_KERNEL); + if (!ap) { + dev_err(cs->dev, "%s: out of memory\n", __func__); + return; + } + ap->id = appl; + + list_add(&ap->ctrlist, &iif->appls); +} + +/* + * release CAPI application + */ +static void gigaset_release_appl(struct capi_ctr *ctr, u16 appl) +{ + struct gigaset_capi_ctr *iif + = container_of(ctr, struct gigaset_capi_ctr, ctr); + struct cardstate *cs = iif->ctr.driverdata; + struct gigaset_capi_appl *ap, *tmp; + + list_for_each_entry_safe(ap, tmp, &iif->appls, ctrlist) + if (ap->id == appl) { + if (ap->connected != APCONN_NONE) { + dev_err(cs->dev, + "%s: application %u still connected\n", + __func__, ap->id); + /* ToDo: clear active connection */ + } + list_del(&ap->ctrlist); + kfree(ap); + } + +} + +/* + * ===================================================================== + * outgoing CAPI message handler + * ===================================================================== + */ + +/* + * helper function: emit reply message with given Info value + */ +static void send_conf(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb, + u16 info) +{ + /* + * _CONF replies always only have NCCI and Info parameters + * so they'll fit into the _REQ message skb + */ + capi_cmsg_answer(&iif->acmsg); + iif->acmsg.Info = info; + capi_cmsg2message(&iif->acmsg, skb->data); + __skb_trim(skb, CAPI_STDCONF_LEN); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + capi_ctr_handle_message(&iif->ctr, ap->id, skb); +} + +/* + * process FACILITY_REQ message + */ +static void do_facility_req(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + struct cardstate *cs = iif->ctr.driverdata; + struct sk_buff *cskb; + u8 *pparam; + unsigned int msgsize = CAPI_FACILITY_CONF_BASELEN; + u16 function, info; + static u8 confparam[10]; /* max. 9 octets + length byte */ + + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + + /* + * Facility Request Parameter is not decoded by capi_message2cmsg() + * encoding depends on Facility Selector + */ + switch (iif->acmsg.FacilitySelector) { + case CAPI_FACILITY_DTMF: /* ToDo */ + info = CapiFacilityNotSupported; + confparam[0] = 2; /* length */ + /* DTMF information: Unknown DTMF request */ + capimsg_setu16(confparam, 1, 2); + break; + + case CAPI_FACILITY_V42BIS: /* not supported */ + info = CapiFacilityNotSupported; + confparam[0] = 2; /* length */ + /* V.42 bis information: not available */ + capimsg_setu16(confparam, 1, 1); + break; + + case CAPI_FACILITY_SUPPSVC: + /* decode Function parameter */ + pparam = iif->acmsg.FacilityRequestParameter; + if (pparam == NULL || *pparam < 2) { + dev_notice(cs->dev, "%s: %s missing\n", "FACILITY_REQ", + "Facility Request Parameter"); + send_conf(iif, ap, skb, CapiIllMessageParmCoding); + return; + } + function = CAPIMSG_U16(pparam, 1); + switch (function) { + case CAPI_SUPPSVC_GETSUPPORTED: + info = CapiSuccess; + /* Supplementary Service specific parameter */ + confparam[3] = 6; /* length */ + /* Supplementary services info: Success */ + capimsg_setu16(confparam, 4, CapiSuccess); + /* Supported Services: none */ + capimsg_setu32(confparam, 6, 0); + break; + /* ToDo: add supported services */ + default: + info = CapiFacilitySpecificFunctionNotSupported; + /* Supplementary Service specific parameter */ + confparam[3] = 2; /* length */ + /* Supplementary services info: not supported */ + capimsg_setu16(confparam, 4, + CapiSupplementaryServiceNotSupported); + } + + /* Facility confirmation parameter */ + confparam[0] = confparam[3] + 3; /* total length */ + /* Function: copy from _REQ message */ + capimsg_setu16(confparam, 1, function); + /* Supplementary Service specific parameter already set above */ + break; + + case CAPI_FACILITY_WAKEUP: /* ToDo */ + info = CapiFacilityNotSupported; + confparam[0] = 2; /* length */ + /* Number of accepted awake request parameters: 0 */ + capimsg_setu16(confparam, 1, 0); + break; + + default: + info = CapiFacilityNotSupported; + confparam[0] = 0; /* empty struct */ + } + + /* send FACILITY_CONF with given Info and confirmation parameter */ + capi_cmsg_answer(&iif->acmsg); + iif->acmsg.Info = info; + iif->acmsg.FacilityConfirmationParameter = confparam; + msgsize += confparam[0]; /* length */ + cskb = alloc_skb(msgsize, GFP_ATOMIC); + if (!cskb) { + dev_err(cs->dev, "%s: out of memory\n", __func__); + return; + } + capi_cmsg2message(&iif->acmsg, __skb_put(cskb, msgsize)); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + capi_ctr_handle_message(&iif->ctr, ap->id, cskb); +} + + +/* + * process LISTEN_REQ message + * just store the masks in the application data structure + */ +static void do_listen_req(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + + /* store listening parameters */ + ap->listenInfoMask = iif->acmsg.InfoMask; + ap->listenCIPmask = iif->acmsg.CIPmask; + send_conf(iif, ap, skb, CapiSuccess); +} + +/* + * process ALERT_REQ message + * nothing to do, Gigaset always alerts anyway + */ +static void do_alert_req(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + send_conf(iif, ap, skb, CapiAlertAlreadySent); +} + +/* + * process CONNECT_REQ message + * allocate a B channel, prepare dial commands, queue a DIAL event, + * emit CONNECT_CONF reply + */ +static void do_connect_req(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + struct cardstate *cs = iif->ctr.driverdata; + _cmsg *cmsg = &iif->acmsg; + struct bc_state *bcs; + char **commands; + char *s; + u8 *pp; + int i, l; + u16 info; + + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + + /* get free B channel & construct PLCI */ + bcs = gigaset_get_free_channel(cs); + if (!bcs) { + dev_notice(cs->dev, "%s: no B channel available\n", + "CONNECT_REQ"); + send_conf(iif, ap, skb, CapiNoPlciAvailable); + return; + } + ap->bcnext = NULL; + bcs->ap = ap; + cmsg->adr.adrPLCI |= (bcs->channel + 1) << 8; + + /* build command table */ + commands = kzalloc(AT_NUM*(sizeof *commands), GFP_KERNEL); + if (!commands) + goto oom; + + /* encode parameter: Called party number */ + pp = cmsg->CalledPartyNumber; + if (pp == NULL || *pp == 0) { + dev_notice(cs->dev, "%s: %s missing\n", + "CONNECT_REQ", "Called party number"); + info = CapiIllMessageParmCoding; + goto error; + } + l = *pp++; + /* check type of number/numbering plan byte */ + switch (*pp) { + case 0x80: /* unknown type / unknown numbering plan */ + case 0x81: /* unknown type / ISDN/Telephony numbering plan */ + break; + default: /* others: warn about potential misinterpretation */ + dev_notice(cs->dev, "%s: %s type/plan 0x%02x unsupported\n", + "CONNECT_REQ", "Called party number", *pp); + } + pp++; + l--; + /* translate "**" internal call prefix to CTP value */ + if (l >= 2 && pp[0] == '*' && pp[1] == '*') { + s = "^SCTP=0\r"; + pp += 2; + l -= 2; + } else { + s = "^SCTP=1\r"; + } + commands[AT_TYPE] = kstrdup(s, GFP_KERNEL); + if (!commands[AT_TYPE]) + goto oom; + commands[AT_DIAL] = kmalloc(l+3, GFP_KERNEL); + if (!commands[AT_DIAL]) + goto oom; + snprintf(commands[AT_DIAL], l+3, "D%*s\r", l, pp); + + /* encode parameter: Calling party number */ + pp = cmsg->CallingPartyNumber; + if (pp != NULL && *pp > 0) { + l = *pp++; + + /* check type of number/numbering plan byte */ + /* ToDo: allow for/handle Ext=1? */ + switch (*pp) { + case 0x00: /* unknown type / unknown numbering plan */ + case 0x01: /* unknown type / ISDN/Telephony num. plan */ + break; + default: + dev_notice(cs->dev, + "%s: %s type/plan 0x%02x unsupported\n", + "CONNECT_REQ", "Calling party number", *pp); + } + pp++; + l--; + + /* check presentation indicator */ + if (!l) { + dev_notice(cs->dev, "%s: %s IE truncated\n", + "CONNECT_REQ", "Calling party number"); + info = CapiIllMessageParmCoding; + goto error; + } + switch (*pp & 0xfc) { /* ignore Screening indicator */ + case 0x80: /* Presentation allowed */ + s = "^SCLIP=1\r"; + break; + case 0xa0: /* Presentation restricted */ + s = "^SCLIP=0\r"; + break; + default: + dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", + "CONNECT_REQ", + "Presentation/Screening indicator", + *pp); + s = "^SCLIP=1\r"; + } + commands[AT_CLIP] = kstrdup(s, GFP_KERNEL); + if (!commands[AT_CLIP]) + goto oom; + pp++; + l--; + + if (l) { + /* number */ + commands[AT_MSN] = kmalloc(l+8, GFP_KERNEL); + if (!commands[AT_MSN]) + goto oom; + snprintf(commands[AT_MSN], l+8, "^SMSN=%*s\r", l, pp); + } + } + + /* check parameter: CIP Value */ + if (cmsg->CIPValue > ARRAY_SIZE(cip2bchlc) || + (cmsg->CIPValue > 0 && cip2bchlc[cmsg->CIPValue].bc == NULL)) { + dev_notice(cs->dev, "%s: unknown CIP value %d\n", + "CONNECT_REQ", cmsg->CIPValue); + info = CapiCipValueUnknown; + goto error; + } + + /* check/encode parameter: BC */ + if (cmsg->BC && cmsg->BC[0]) { + /* explicit BC overrides CIP */ + l = 2*cmsg->BC[0] + 7; + commands[AT_BC] = kmalloc(l, GFP_KERNEL); + if (!commands[AT_BC]) + goto oom; + strcpy(commands[AT_BC], "^SBC="); + decode_ie(cmsg->BC, commands[AT_BC]+5); + strcpy(commands[AT_BC] + l - 2, "\r"); + } else if (cip2bchlc[cmsg->CIPValue].bc) { + l = strlen(cip2bchlc[cmsg->CIPValue].bc) + 7; + commands[AT_BC] = kmalloc(l, GFP_KERNEL); + if (!commands[AT_BC]) + goto oom; + snprintf(commands[AT_BC], l, "^SBC=%s\r", + cip2bchlc[cmsg->CIPValue].bc); + } + + /* check/encode parameter: HLC */ + if (cmsg->HLC && cmsg->HLC[0]) { + /* explicit HLC overrides CIP */ + l = 2*cmsg->HLC[0] + 7; + commands[AT_HLC] = kmalloc(l, GFP_KERNEL); + if (!commands[AT_HLC]) + goto oom; + strcpy(commands[AT_HLC], "^SHLC="); + decode_ie(cmsg->HLC, commands[AT_HLC]+5); + strcpy(commands[AT_HLC] + l - 2, "\r"); + } else if (cip2bchlc[cmsg->CIPValue].hlc) { + l = strlen(cip2bchlc[cmsg->CIPValue].hlc) + 7; + commands[AT_HLC] = kmalloc(l, GFP_KERNEL); + if (!commands[AT_HLC]) + goto oom; + snprintf(commands[AT_HLC], l, "^SHLC=%s\r", + cip2bchlc[cmsg->CIPValue].hlc); + } + + /* check/encode parameter: B Protocol */ + if (cmsg->BProtocol == CAPI_DEFAULT) { + bcs->proto2 = L2_HDLC; + dev_warn(cs->dev, + "B2 Protocol X.75 SLP unsupported, using Transparent\n"); + } else { + switch (cmsg->B1protocol) { + case 0: + bcs->proto2 = L2_HDLC; + break; + case 1: + bcs->proto2 = L2_BITSYNC; + break; + default: + dev_warn(cs->dev, + "B1 Protocol %u unsupported, using Transparent\n", + cmsg->B1protocol); + bcs->proto2 = L2_BITSYNC; + } + if (cmsg->B2protocol != 1) + dev_warn(cs->dev, + "B2 Protocol %u unsupported, using Transparent\n", + cmsg->B2protocol); + if (cmsg->B3protocol != 0) + dev_warn(cs->dev, + "B3 Protocol %u unsupported, using Transparent\n", + cmsg->B3protocol); + ignore_cstruct_param(cs, cmsg->B1configuration, + "CONNECT_REQ", "B1 Configuration"); + ignore_cstruct_param(cs, cmsg->B2configuration, + "CONNECT_REQ", "B2 Configuration"); + ignore_cstruct_param(cs, cmsg->B3configuration, + "CONNECT_REQ", "B3 Configuration"); + } + commands[AT_PROTO] = kmalloc(9, GFP_KERNEL); + if (!commands[AT_PROTO]) + goto oom; + snprintf(commands[AT_PROTO], 9, "^SBPR=%u\r", bcs->proto2); + + /* ToDo: check/encode remaining parameters */ + ignore_cstruct_param(cs, cmsg->CalledPartySubaddress, + "CONNECT_REQ", "Called pty subaddr"); + ignore_cstruct_param(cs, cmsg->CallingPartySubaddress, + "CONNECT_REQ", "Calling pty subaddr"); + ignore_cstruct_param(cs, cmsg->LLC, + "CONNECT_REQ", "LLC"); + ignore_cmstruct_param(cs, cmsg->AdditionalInfo, + "CONNECT_REQ", "Additional Info"); + + /* encode parameter: B channel to use */ + commands[AT_ISO] = kmalloc(9, GFP_KERNEL); + if (!commands[AT_ISO]) + goto oom; + snprintf(commands[AT_ISO], 9, "^SISO=%u\r", + (unsigned) bcs->channel + 1); + + /* queue & schedule EV_DIAL event */ + if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, commands, + bcs->at_state.seq_index, NULL)) + goto oom; + gig_dbg(DEBUG_CMD, "scheduling DIAL"); + gigaset_schedule_event(cs); + ap->connected = APCONN_SETUP; + send_conf(iif, ap, skb, CapiSuccess); + return; + +oom: + dev_err(cs->dev, "%s: out of memory\n", __func__); + info = CAPI_MSGOSRESOURCEERR; +error: + if (commands) + for (i = 0; i < AT_NUM; i++) + kfree(commands[i]); + kfree(commands); + gigaset_free_channel(bcs); + send_conf(iif, ap, skb, info); +} + +/* + * process CONNECT_RESP message + * checks protocol parameters and queues an ACCEPT or HUP event + */ +static void do_connect_resp(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + struct cardstate *cs = iif->ctr.driverdata; + _cmsg *cmsg = &iif->acmsg; + struct bc_state *bcs; + struct gigaset_capi_appl *oap; + int channel; + + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + dev_kfree_skb(skb); + + /* extract and check channel number from PLCI */ + channel = (cmsg->adr.adrPLCI >> 8) & 0xff; + if (!channel || channel > cs->channels) { + dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", + "CONNECT_RESP", "PLCI", cmsg->adr.adrPLCI); + return; + } + bcs = cs->bcs + channel - 1; + + switch (cmsg->Reject) { + case 0: /* Accept */ + /* drop all competing applications, keep only this one */ + for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) + if (oap != ap) + send_disconnect_ind(bcs, oap, + CapiCallGivenToOtherApplication); + ap->bcnext = NULL; + bcs->ap = ap; + bcs->chstate |= CHS_NOTIFY_LL; + + /* check/encode B channel protocol */ + if (cmsg->BProtocol == CAPI_DEFAULT) { + bcs->proto2 = L2_HDLC; + dev_warn(cs->dev, + "B2 Protocol X.75 SLP unsupported, using Transparent\n"); + } else { + switch (cmsg->B1protocol) { + case 0: + bcs->proto2 = L2_HDLC; + break; + case 1: + bcs->proto2 = L2_BITSYNC; + break; + default: + dev_warn(cs->dev, + "B1 Protocol %u unsupported, using Transparent\n", + cmsg->B1protocol); + bcs->proto2 = L2_BITSYNC; + } + if (cmsg->B2protocol != 1) + dev_warn(cs->dev, + "B2 Protocol %u unsupported, using Transparent\n", + cmsg->B2protocol); + if (cmsg->B3protocol != 0) + dev_warn(cs->dev, + "B3 Protocol %u unsupported, using Transparent\n", + cmsg->B3protocol); + ignore_cstruct_param(cs, cmsg->B1configuration, + "CONNECT_RESP", "B1 Configuration"); + ignore_cstruct_param(cs, cmsg->B2configuration, + "CONNECT_RESP", "B2 Configuration"); + ignore_cstruct_param(cs, cmsg->B3configuration, + "CONNECT_RESP", "B3 Configuration"); + } + + /* ToDo: check/encode remaining parameters */ + ignore_cstruct_param(cs, cmsg->ConnectedNumber, + "CONNECT_RESP", "Connected Number"); + ignore_cstruct_param(cs, cmsg->ConnectedSubaddress, + "CONNECT_RESP", "Connected Subaddress"); + ignore_cstruct_param(cs, cmsg->LLC, + "CONNECT_RESP", "LLC"); + ignore_cmstruct_param(cs, cmsg->AdditionalInfo, + "CONNECT_RESP", "Additional Info"); + + /* Accept call */ + if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state, + EV_ACCEPT, NULL, 0, NULL)) + return; + gig_dbg(DEBUG_CMD, "scheduling ACCEPT"); + gigaset_schedule_event(cs); + return; + + case 1: /* Ignore */ + /* send DISCONNECT_IND to this application */ + send_disconnect_ind(bcs, ap, 0); + + /* remove it from the list of listening apps */ + if (bcs->ap == ap) { + bcs->ap = ap->bcnext; + if (bcs->ap == NULL) + /* last one: stop ev-layer hupD notifications */ + bcs->chstate &= ~CHS_NOTIFY_LL; + return; + } + for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) { + if (oap->bcnext == ap) { + oap->bcnext = oap->bcnext->bcnext; + return; + } + } + dev_err(cs->dev, "%s: application %u not found\n", + __func__, ap->id); + return; + + default: /* Reject */ + /* drop all competing applications, keep only this one */ + for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) + if (oap != ap) + send_disconnect_ind(bcs, oap, + CapiCallGivenToOtherApplication); + ap->bcnext = NULL; + bcs->ap = ap; + + /* reject call - will trigger DISCONNECT_IND for this app */ + dev_info(cs->dev, "%s: Reject=%x\n", + "CONNECT_RESP", cmsg->Reject); + if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state, + EV_HUP, NULL, 0, NULL)) + return; + gig_dbg(DEBUG_CMD, "scheduling HUP"); + gigaset_schedule_event(cs); + return; + } +} + +/* + * process CONNECT_B3_REQ message + * build NCCI and emit CONNECT_B3_CONF reply + */ +static void do_connect_b3_req(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + struct cardstate *cs = iif->ctr.driverdata; + int channel; + + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + + /* extract and check channel number from PLCI */ + channel = (iif->acmsg.adr.adrPLCI >> 8) & 0xff; + if (!channel || channel > cs->channels) { + dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", + "CONNECT_B3_REQ", "PLCI", iif->acmsg.adr.adrPLCI); + send_conf(iif, ap, skb, CapiIllContrPlciNcci); + return; + } + + /* mark logical connection active */ + ap->connected = APCONN_ACTIVE; + + /* build NCCI: always 1 (one B3 connection only) */ + iif->acmsg.adr.adrNCCI |= 1 << 16; + + /* NCPI parameter: not applicable for B3 Transparent */ + ignore_cstruct_param(cs, iif->acmsg.NCPI, + "CONNECT_B3_REQ", "NCPI"); + send_conf(iif, ap, skb, + (iif->acmsg.NCPI && iif->acmsg.NCPI[0]) ? + CapiNcpiNotSupportedByProtocol : CapiSuccess); +} + +/* + * process CONNECT_B3_RESP message + * Depending on the Reject parameter, either emit CONNECT_B3_ACTIVE_IND + * or queue EV_HUP and emit DISCONNECT_B3_IND. + * The emitted message is always shorter than the received one, + * allowing to reuse the skb. + */ +static void do_connect_b3_resp(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + struct cardstate *cs = iif->ctr.driverdata; + struct bc_state *bcs = NULL; + int channel; + unsigned int msgsize; + u8 command; + + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + + /* extract and check channel number and NCCI */ + channel = (iif->acmsg.adr.adrNCCI >> 8) & 0xff; + if (!channel || channel > cs->channels || + ((iif->acmsg.adr.adrNCCI >> 16) & 0xffff) != 1) { + dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", + "CONNECT_B3_RESP", "NCCI", iif->acmsg.adr.adrNCCI); + dev_kfree_skb(skb); + return; + } + bcs = &cs->bcs[channel-1]; + + if (iif->acmsg.Reject) { + /* Reject: clear B3 connect received flag */ + ap->connected = APCONN_SETUP; + + /* trigger hangup, causing eventual DISCONNECT_IND */ + if (!gigaset_add_event(cs, &bcs->at_state, + EV_HUP, NULL, 0, NULL)) { + dev_err(cs->dev, "%s: out of memory\n", __func__); + dev_kfree_skb(skb); + return; + } + gig_dbg(DEBUG_CMD, "scheduling HUP"); + gigaset_schedule_event(cs); + + /* emit DISCONNECT_B3_IND */ + command = CAPI_DISCONNECT_B3; + msgsize = CAPI_DISCONNECT_B3_IND_BASELEN; + } else { + /* + * Accept: emit CONNECT_B3_ACTIVE_IND immediately, as + * we only send CONNECT_B3_IND if the B channel is up + */ + command = CAPI_CONNECT_B3_ACTIVE; + msgsize = CAPI_CONNECT_B3_ACTIVE_IND_BASELEN; + } + capi_cmsg_header(&iif->acmsg, ap->id, command, CAPI_IND, + ap->nextMessageNumber++, iif->acmsg.adr.adrNCCI); + __skb_trim(skb, msgsize); + capi_cmsg2message(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + capi_ctr_handle_message(&iif->ctr, ap->id, skb); +} + +/* + * process DISCONNECT_REQ message + * schedule EV_HUP and emit DISCONNECT_B3_IND if necessary, + * emit DISCONNECT_CONF reply + */ +static void do_disconnect_req(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + struct cardstate *cs = iif->ctr.driverdata; + struct bc_state *bcs; + _cmsg *b3cmsg; + struct sk_buff *b3skb; + int channel; + + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + + /* extract and check channel number from PLCI */ + channel = (iif->acmsg.adr.adrPLCI >> 8) & 0xff; + if (!channel || channel > cs->channels) { + dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", + "DISCONNECT_REQ", "PLCI", iif->acmsg.adr.adrPLCI); + send_conf(iif, ap, skb, CapiIllContrPlciNcci); + return; + } + bcs = cs->bcs + channel - 1; + + /* ToDo: process parameter: Additional info */ + ignore_cmstruct_param(cs, iif->acmsg.AdditionalInfo, + "DISCONNECT_REQ", "Additional Info"); + + /* skip if DISCONNECT_IND already sent */ + if (!ap->connected) + return; + + /* check for active logical connection */ + if (ap->connected >= APCONN_ACTIVE) { + /* + * emit DISCONNECT_B3_IND with cause 0x3301 + * use separate cmsg structure, as the content of iif->acmsg + * is still needed for creating the _CONF message + */ + b3cmsg = kmalloc(sizeof(*b3cmsg), GFP_KERNEL); + if (!b3cmsg) { + dev_err(cs->dev, "%s: out of memory\n", __func__); + send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); + return; + } + capi_cmsg_header(b3cmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND, + ap->nextMessageNumber++, + iif->acmsg.adr.adrPLCI | (1 << 16)); + b3cmsg->Reason_B3 = CapiProtocolErrorLayer1; + b3skb = alloc_skb(CAPI_DISCONNECT_B3_IND_BASELEN, GFP_KERNEL); + if (b3skb == NULL) { + dev_err(cs->dev, "%s: out of memory\n", __func__); + send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); + return; + } + capi_cmsg2message(b3cmsg, + __skb_put(b3skb, CAPI_DISCONNECT_B3_IND_BASELEN)); + kfree(b3cmsg); + capi_ctr_handle_message(&iif->ctr, ap->id, b3skb); + } + + /* trigger hangup, causing eventual DISCONNECT_IND */ + if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) { + dev_err(cs->dev, "%s: out of memory\n", __func__); + send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); + return; + } + gig_dbg(DEBUG_CMD, "scheduling HUP"); + gigaset_schedule_event(cs); + + /* emit reply */ + send_conf(iif, ap, skb, CapiSuccess); +} + +/* + * process DISCONNECT_B3_REQ message + * schedule EV_HUP and emit DISCONNECT_B3_CONF reply + */ +static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + struct cardstate *cs = iif->ctr.driverdata; + int channel; + + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + + /* extract and check channel number and NCCI */ + channel = (iif->acmsg.adr.adrNCCI >> 8) & 0xff; + if (!channel || channel > cs->channels || + ((iif->acmsg.adr.adrNCCI >> 16) & 0xffff) != 1) { + dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", + "DISCONNECT_B3_REQ", "NCCI", iif->acmsg.adr.adrNCCI); + send_conf(iif, ap, skb, CapiIllContrPlciNcci); + return; + } + + /* reject if logical connection not active */ + if (ap->connected < APCONN_ACTIVE) { + send_conf(iif, ap, skb, + CapiMessageNotSupportedInCurrentState); + return; + } + + /* trigger hangup, causing eventual DISCONNECT_B3_IND */ + if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state, + EV_HUP, NULL, 0, NULL)) { + dev_err(cs->dev, "%s: out of memory\n", __func__); + send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); + return; + } + gig_dbg(DEBUG_CMD, "scheduling HUP"); + gigaset_schedule_event(cs); + + /* NCPI parameter: not applicable for B3 Transparent */ + ignore_cstruct_param(cs, iif->acmsg.NCPI, + "DISCONNECT_B3_REQ", "NCPI"); + send_conf(iif, ap, skb, + (iif->acmsg.NCPI && iif->acmsg.NCPI[0]) ? + CapiNcpiNotSupportedByProtocol : CapiSuccess); +} + +/* + * process DATA_B3_REQ message + */ +static void do_data_b3_req(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + struct cardstate *cs = iif->ctr.driverdata; + int channel = CAPIMSG_PLCI_PART(skb->data); + u16 ncci = CAPIMSG_NCCI_PART(skb->data); + u16 msglen = CAPIMSG_LEN(skb->data); + u16 datalen = CAPIMSG_DATALEN(skb->data); + u16 flags = CAPIMSG_FLAGS(skb->data); + + /* frequent message, avoid _cmsg overhead */ + dump_rawmsg(DEBUG_LLDATA, "DATA_B3_REQ", skb->data); + + gig_dbg(DEBUG_LLDATA, + "Receiving data from LL (ch: %d, flg: %x, sz: %d|%d)", + channel, flags, msglen, datalen); + + /* check parameters */ + if (channel == 0 || channel > cs->channels || ncci != 1) { + dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", + "DATA_B3_REQ", "NCCI", CAPIMSG_NCCI(skb->data)); + send_conf(iif, ap, skb, CapiIllContrPlciNcci); + return; + } + if (msglen != CAPI_DATA_B3_REQ_LEN && msglen != CAPI_DATA_B3_REQ_LEN64) + dev_notice(cs->dev, "%s: unexpected length %d\n", + "DATA_B3_REQ", msglen); + if (msglen + datalen != skb->len) + dev_notice(cs->dev, "%s: length mismatch (%d+%d!=%d)\n", + "DATA_B3_REQ", msglen, datalen, skb->len); + if (msglen + datalen > skb->len) { + /* message too short for announced data length */ + send_conf(iif, ap, skb, CapiIllMessageParmCoding); /* ? */ + return; + } + if (flags & CAPI_FLAGS_RESERVED) { + dev_notice(cs->dev, "%s: reserved flags set (%x)\n", + "DATA_B3_REQ", flags); + send_conf(iif, ap, skb, CapiIllMessageParmCoding); + return; + } + + /* reject if logical connection not active */ + if (ap->connected < APCONN_ACTIVE) { + send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState); + return; + } + + /* + * pull CAPI message from skb, + * pass payload data to device-specific module + * CAPI message will be preserved in headroom + */ + skb_pull(skb, msglen); + if (cs->ops->send_skb(&cs->bcs[channel-1], skb) < 0) { + send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); + return; + } + + /* DATA_B3_CONF reply will be sent by gigaset_skb_sent() */ + + /* + * ToDo: honor unset "delivery confirmation" bit + * (send DATA_B3_CONF immediately?) + */ +} + +/* + * process RESET_B3_REQ message + * just always reply "not supported by current protocol" + */ +static void do_reset_b3_req(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + send_conf(iif, ap, skb, + CapiResetProcedureNotSupportedByCurrentProtocol); +} + +/* + * dump unsupported/ignored messages at most twice per minute, + * some apps send those very frequently + */ +static unsigned long ignored_msg_dump_time; + +/* + * unsupported CAPI message handler + */ +static void do_unsupported(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + if (printk_timed_ratelimit(&ignored_msg_dump_time, 30 * 1000)) + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState); +} + +/* + * CAPI message handler: no-op + */ +static void do_nothing(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + if (printk_timed_ratelimit(&ignored_msg_dump_time, 30 * 1000)) { + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + } + dev_kfree_skb(skb); +} + +static void do_data_b3_resp(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + dump_rawmsg(DEBUG_LLDATA, __func__, skb->data); + dev_kfree_skb(skb); +} + +/* table of outgoing CAPI message handlers with lookup function */ +typedef void (*capi_send_handler_t)(struct gigaset_capi_ctr *, + struct gigaset_capi_appl *, + struct sk_buff *); + +static struct { + u16 cmd; + capi_send_handler_t handler; +} capi_send_handler_table[] = { + /* most frequent messages first for faster lookup */ + { CAPI_DATA_B3_REQ, do_data_b3_req }, + { CAPI_DATA_B3_RESP, do_data_b3_resp }, + + { CAPI_ALERT_REQ, do_alert_req }, + { CAPI_CONNECT_ACTIVE_RESP, do_nothing }, + { CAPI_CONNECT_B3_ACTIVE_RESP, do_nothing }, + { CAPI_CONNECT_B3_REQ, do_connect_b3_req }, + { CAPI_CONNECT_B3_RESP, do_connect_b3_resp }, + { CAPI_CONNECT_B3_T90_ACTIVE_RESP, do_nothing }, + { CAPI_CONNECT_REQ, do_connect_req }, + { CAPI_CONNECT_RESP, do_connect_resp }, + { CAPI_DISCONNECT_B3_REQ, do_disconnect_b3_req }, + { CAPI_DISCONNECT_B3_RESP, do_nothing }, + { CAPI_DISCONNECT_REQ, do_disconnect_req }, + { CAPI_DISCONNECT_RESP, do_nothing }, + { CAPI_FACILITY_REQ, do_facility_req }, + { CAPI_FACILITY_RESP, do_nothing }, + { CAPI_LISTEN_REQ, do_listen_req }, + { CAPI_SELECT_B_PROTOCOL_REQ, do_unsupported }, + { CAPI_RESET_B3_REQ, do_reset_b3_req }, + { CAPI_RESET_B3_RESP, do_nothing }, + + /* + * ToDo: support overlap sending (requires ev-layer state + * machine extension to generate additional ATD commands) + */ + { CAPI_INFO_REQ, do_unsupported }, + { CAPI_INFO_RESP, do_nothing }, + + /* + * ToDo: what's the proper response for these? + */ + { CAPI_MANUFACTURER_REQ, do_nothing }, + { CAPI_MANUFACTURER_RESP, do_nothing }, +}; + +/* look up handler */ +static inline capi_send_handler_t lookup_capi_send_handler(const u16 cmd) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(capi_send_handler_table); i++) + if (capi_send_handler_table[i].cmd == cmd) + return capi_send_handler_table[i].handler; + return NULL; +} + + +/** + * gigaset_send_message() - accept a CAPI message from an application + * @ctr: controller descriptor structure. + * @skb: CAPI message. + * + * Return value: CAPI error code + * Note: capidrv (and probably others, too) only uses the return value to + * decide whether it has to free the skb (only if result != CAPI_NOERROR (0)) + */ +static u16 gigaset_send_message(struct capi_ctr *ctr, struct sk_buff *skb) +{ + struct gigaset_capi_ctr *iif + = container_of(ctr, struct gigaset_capi_ctr, ctr); + struct cardstate *cs = ctr->driverdata; + struct gigaset_capi_appl *ap; + capi_send_handler_t handler; + + /* can only handle linear sk_buffs */ + if (skb_linearize(skb) < 0) { + dev_warn(cs->dev, "%s: skb_linearize failed\n", __func__); + return CAPI_MSGOSRESOURCEERR; + } + + /* retrieve application data structure */ + ap = get_appl(iif, CAPIMSG_APPID(skb->data)); + if (!ap) { + dev_notice(cs->dev, "%s: application %u not registered\n", + __func__, CAPIMSG_APPID(skb->data)); + return CAPI_ILLAPPNR; + } + + /* look up command */ + handler = lookup_capi_send_handler(CAPIMSG_CMD(skb->data)); + if (!handler) { + /* unknown/unsupported message type */ + if (printk_ratelimit()) + dev_notice(cs->dev, "%s: unsupported message %u\n", + __func__, CAPIMSG_CMD(skb->data)); + return CAPI_ILLCMDORSUBCMDORMSGTOSMALL; + } + + /* serialize */ + if (atomic_add_return(1, &iif->sendqlen) > 1) { + /* queue behind other messages */ + skb_queue_tail(&iif->sendqueue, skb); + return CAPI_NOERROR; + } + + /* process message */ + handler(iif, ap, skb); + + /* process other messages arrived in the meantime */ + while (atomic_sub_return(1, &iif->sendqlen) > 0) { + skb = skb_dequeue(&iif->sendqueue); + if (!skb) { + /* should never happen */ + dev_err(cs->dev, "%s: send queue empty\n", __func__); + continue; + } + ap = get_appl(iif, CAPIMSG_APPID(skb->data)); + if (!ap) { + /* could that happen? */ + dev_warn(cs->dev, "%s: application %u vanished\n", + __func__, CAPIMSG_APPID(skb->data)); + continue; + } + handler = lookup_capi_send_handler(CAPIMSG_CMD(skb->data)); + if (!handler) { + /* should never happen */ + dev_err(cs->dev, "%s: handler %x vanished\n", + __func__, CAPIMSG_CMD(skb->data)); + continue; + } + handler(iif, ap, skb); + } + + return CAPI_NOERROR; +} + +/** + * gigaset_procinfo() - build single line description for controller + * @ctr: controller descriptor structure. + * + * Return value: pointer to generated string (null terminated) + */ +static char *gigaset_procinfo(struct capi_ctr *ctr) +{ + return ctr->name; /* ToDo: more? */ +} + +/** + * gigaset_ctr_read_proc() - build controller proc file entry + * @page: buffer of PAGE_SIZE bytes for receiving the entry. + * @start: unused. + * @off: unused. + * @count: unused. + * @eof: unused. + * @ctr: controller descriptor structure. + * + * Return value: length of generated entry + */ +static int gigaset_ctr_read_proc(char *page, char **start, off_t off, + int count, int *eof, struct capi_ctr *ctr) +{ + struct cardstate *cs = ctr->driverdata; + char *s; + int i; + int len = 0; + len += sprintf(page+len, "%-16s %s\n", "name", ctr->name); + len += sprintf(page+len, "%-16s %s %s\n", "dev", + dev_driver_string(cs->dev), dev_name(cs->dev)); + len += sprintf(page+len, "%-16s %d\n", "id", cs->myid); + if (cs->gotfwver) + len += sprintf(page+len, "%-16s %d.%d.%d.%d\n", "firmware", + cs->fwver[0], cs->fwver[1], cs->fwver[2], cs->fwver[3]); + len += sprintf(page+len, "%-16s %d\n", "channels", + cs->channels); + len += sprintf(page+len, "%-16s %s\n", "onechannel", + cs->onechannel ? "yes" : "no"); + + switch (cs->mode) { + case M_UNKNOWN: + s = "unknown"; + break; + case M_CONFIG: + s = "config"; + break; + case M_UNIMODEM: + s = "Unimodem"; + break; + case M_CID: + s = "CID"; + break; + default: + s = "??"; + } + len += sprintf(page+len, "%-16s %s\n", "mode", s); + + switch (cs->mstate) { + case MS_UNINITIALIZED: + s = "uninitialized"; + break; + case MS_INIT: + s = "init"; + break; + case MS_LOCKED: + s = "locked"; + break; + case MS_SHUTDOWN: + s = "shutdown"; + break; + case MS_RECOVER: + s = "recover"; + break; + case MS_READY: + s = "ready"; + break; + default: + s = "??"; + } + len += sprintf(page+len, "%-16s %s\n", "mstate", s); + + len += sprintf(page+len, "%-16s %s\n", "running", + cs->running ? "yes" : "no"); + len += sprintf(page+len, "%-16s %s\n", "connected", + cs->connected ? "yes" : "no"); + len += sprintf(page+len, "%-16s %s\n", "isdn_up", + cs->isdn_up ? "yes" : "no"); + len += sprintf(page+len, "%-16s %s\n", "cidmode", + cs->cidmode ? "yes" : "no"); + + for (i = 0; i < cs->channels; i++) { + len += sprintf(page+len, "[%d]%-13s %d\n", i, "corrupted", + cs->bcs[i].corrupted); + len += sprintf(page+len, "[%d]%-13s %d\n", i, "trans_down", + cs->bcs[i].trans_down); + len += sprintf(page+len, "[%d]%-13s %d\n", i, "trans_up", + cs->bcs[i].trans_up); + len += sprintf(page+len, "[%d]%-13s %d\n", i, "chstate", + cs->bcs[i].chstate); + switch (cs->bcs[i].proto2) { + case L2_BITSYNC: + s = "bitsync"; + break; + case L2_HDLC: + s = "HDLC"; + break; + case L2_VOICE: + s = "voice"; + break; + default: + s = "??"; + } + len += sprintf(page+len, "[%d]%-13s %s\n", i, "proto2", s); + } + return len; +} + + +static struct capi_driver capi_driver_gigaset = { + .name = "gigaset", + .revision = "1.0", +}; + +/** + * gigaset_isdn_register() - register to LL + * @cs: device descriptor structure. + * @isdnid: device name. + * + * Called by main module to register the device with the LL. + * + * Return value: 1 for success, 0 for failure + */ +int gigaset_isdn_register(struct cardstate *cs, const char *isdnid) +{ + struct gigaset_capi_ctr *iif; + int rc; + + pr_info("Kernel CAPI interface\n"); + + iif = kmalloc(sizeof(*iif), GFP_KERNEL); + if (!iif) { + pr_err("%s: out of memory\n", __func__); + return 0; + } + + /* register driver with CAPI (ToDo: what for?) */ + register_capi_driver(&capi_driver_gigaset); + + /* prepare controller structure */ + iif->ctr.owner = THIS_MODULE; + iif->ctr.driverdata = cs; + strncpy(iif->ctr.name, isdnid, sizeof(iif->ctr.name)); + iif->ctr.driver_name = "gigaset"; + iif->ctr.load_firmware = gigaset_load_firmware; + iif->ctr.reset_ctr = gigaset_reset_ctr; + iif->ctr.register_appl = gigaset_register_appl; + iif->ctr.release_appl = gigaset_release_appl; + iif->ctr.send_message = gigaset_send_message; + iif->ctr.procinfo = gigaset_procinfo; + iif->ctr.ctr_read_proc = gigaset_ctr_read_proc; + INIT_LIST_HEAD(&iif->appls); + skb_queue_head_init(&iif->sendqueue); + atomic_set(&iif->sendqlen, 0); + + /* register controller with CAPI */ + rc = attach_capi_ctr(&iif->ctr); + if (rc) { + pr_err("attach_capi_ctr failed (%d)\n", rc); + unregister_capi_driver(&capi_driver_gigaset); + kfree(iif); + return 0; + } + + cs->iif = iif; + cs->hw_hdr_len = CAPI_DATA_B3_REQ_LEN; + return 1; +} + +/** + * gigaset_isdn_unregister() - unregister from LL + * @cs: device descriptor structure. + * + * Called by main module to unregister the device from the LL. + */ +void gigaset_isdn_unregister(struct cardstate *cs) +{ + struct gigaset_capi_ctr *iif = cs->iif; + + detach_capi_ctr(&iif->ctr); + kfree(iif); + cs->iif = NULL; + unregister_capi_driver(&capi_driver_gigaset); +} diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 15dc0fc28a96..1d2ae2e05e0b 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -207,6 +207,32 @@ int gigaset_get_channel(struct bc_state *bcs) return 1; } +struct bc_state *gigaset_get_free_channel(struct cardstate *cs) +{ + unsigned long flags; + int i; + + spin_lock_irqsave(&cs->lock, flags); + if (!try_module_get(cs->driver->owner)) { + gig_dbg(DEBUG_ANY, + "could not get module for allocating channel"); + spin_unlock_irqrestore(&cs->lock, flags); + return NULL; + } + for (i = 0; i < cs->channels; ++i) + if (!cs->bcs[i].use_count) { + ++cs->bcs[i].use_count; + cs->bcs[i].busy = 1; + spin_unlock_irqrestore(&cs->lock, flags); + gig_dbg(DEBUG_ANY, "allocated channel %d", i); + return cs->bcs + i; + } + module_put(cs->driver->owner); + spin_unlock_irqrestore(&cs->lock, flags); + gig_dbg(DEBUG_ANY, "no free channel"); + return NULL; +} + void gigaset_free_channel(struct bc_state *bcs) { unsigned long flags; diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index cb25d2b834b9..369927f90729 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c @@ -291,21 +291,23 @@ struct reply_t gigaset_tab_cid[] = {RSP_OK, 602,602, -1, 603, 5, {ACT_CMD+AT_PROTO}}, {RSP_OK, 603,603, -1, 604, 5, {ACT_CMD+AT_TYPE}}, {RSP_OK, 604,604, -1, 605, 5, {ACT_CMD+AT_MSN}}, - {RSP_OK, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}}, - {RSP_NULL, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}}, - {RSP_OK, 606,606, -1, 607, 5, {0}, "+VLS=17\r"}, - {RSP_OK, 607,607, -1, 608,-1}, - {RSP_ZSAU, 608,608,ZSAU_PROCEEDING, 609, 5, {ACT_CMD+AT_DIAL}}, - {RSP_OK, 609,609, -1, 650, 0, {ACT_DIALING}}, - - {RSP_ERROR, 601,609, -1, 0, 0, {ACT_ABORTDIAL}}, - {EV_TIMEOUT, 601,609, -1, 0, 0, {ACT_ABORTDIAL}}, + {RSP_NULL, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} }, + {RSP_OK, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} }, + {RSP_NULL, 606, 606, -1, 607, 5, {ACT_CMD+AT_ISO} }, + {RSP_OK, 606, 606, -1, 607, 5, {ACT_CMD+AT_ISO} }, + {RSP_OK, 607, 607, -1, 608, 5, {0}, "+VLS=17\r"}, + {RSP_OK, 608, 608, -1, 609, -1}, + {RSP_ZSAU, 609, 609, ZSAU_PROCEEDING, 610, 5, {ACT_CMD+AT_DIAL} }, + {RSP_OK, 610, 610, -1, 650, 0, {ACT_DIALING} }, + + {RSP_ERROR, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} }, + {EV_TIMEOUT, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} }, /* optional dialing responses */ {EV_BC_OPEN, 650,650, -1, 651,-1}, - {RSP_ZVLS, 608,651, 17, -1,-1, {ACT_DEBUG}}, - {RSP_ZCTP, 609,651, -1, -1,-1, {ACT_DEBUG}}, - {RSP_ZCPN, 609,651, -1, -1,-1, {ACT_DEBUG}}, + {RSP_ZVLS, 609, 651, 17, -1, -1, {ACT_DEBUG} }, + {RSP_ZCTP, 610, 651, -1, -1, -1, {ACT_DEBUG} }, + {RSP_ZCPN, 610, 651, -1, -1, -1, {ACT_DEBUG} }, {RSP_ZSAU, 650,651,ZSAU_CALL_DELIVERED, -1,-1, {ACT_DEBUG}}, /* connect */ diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 1185da2dbf61..4749ef100fd3 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -191,7 +191,9 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, #define AT_PROTO 4 #define AT_TYPE 5 #define AT_HLC 6 -#define AT_NUM 7 +#define AT_CLIP 7 +/* total number */ +#define AT_NUM 8 /* variables in struct at_state_t */ #define VAR_ZSAU 0 @@ -412,6 +414,8 @@ struct bc_state { struct usb_bc_state *usb; /* usb hardware driver (m105) */ struct bas_bc_state *bas; /* usb hardware driver (base) */ } hw; + + void *ap; /* LL application structure */ }; struct cardstate { @@ -725,6 +729,7 @@ void gigaset_bcs_reinit(struct bc_state *bcs); void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, struct cardstate *cs, int cid); int gigaset_get_channel(struct bc_state *bcs); +struct bc_state *gigaset_get_free_channel(struct cardstate *cs); void gigaset_free_channel(struct bc_state *bcs); int gigaset_get_channels(struct cardstate *cs); void gigaset_free_channels(struct cardstate *cs); -- cgit v1.2.2 From ec1b4cf74c81bfd0fbe5bf62bafc86c45917e72f Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 5 Oct 2009 05:58:39 +0000 Subject: net: mark net_proto_ops as const All usages of structure net_proto_ops should be declared const. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/isdn/mISDN/socket.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c index feb0fa45b664..28182ed8dea1 100644 --- a/drivers/isdn/mISDN/socket.c +++ b/drivers/isdn/mISDN/socket.c @@ -808,8 +808,7 @@ mISDN_sock_create(struct net *net, struct socket *sock, int proto) return err; } -static struct -net_proto_family mISDN_sock_family_ops = { +static const struct net_proto_family mISDN_sock_family_ops = { .owner = THIS_MODULE, .family = PF_ISDN, .create = mISDN_sock_create, -- cgit v1.2.2 From 6c91191668d32ea15e6950de4ee35b6c75cf4da8 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sun, 25 Oct 2009 09:29:37 +0000 Subject: gigaset: CAPI module readability improvements Replace the "ignoring Additional Info" warning message by better readable ones citing the specific subparameters being ignored. Make parts of the code more readable by using a local cmsg pointer variable. Impact: readability improvement Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/capi.c | 144 +++++++++++++++++++++++++------------------- 1 file changed, 81 insertions(+), 63 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index c276a925b36f..ac0a2da1eef6 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -168,14 +168,6 @@ static inline void ignore_cstruct_param(struct cardstate *cs, _cstruct param, msgname, paramname); } -static inline void ignore_cmstruct_param(struct cardstate *cs, _cmstruct param, - char *msgname, char *paramname) -{ - if (param != CAPI_DEFAULT) - dev_warn(cs->dev, "%s: ignoring unsupported parameter: %s\n", - msgname, paramname); -} - /* * check for legal hex digit */ @@ -1062,6 +1054,7 @@ static void do_facility_req(struct gigaset_capi_ctr *iif, struct sk_buff *skb) { struct cardstate *cs = iif->ctr.driverdata; + _cmsg *cmsg = &iif->acmsg; struct sk_buff *cskb; u8 *pparam; unsigned int msgsize = CAPI_FACILITY_CONF_BASELEN; @@ -1069,14 +1062,14 @@ static void do_facility_req(struct gigaset_capi_ctr *iif, static u8 confparam[10]; /* max. 9 octets + length byte */ /* decode message */ - capi_message2cmsg(&iif->acmsg, skb->data); - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + capi_message2cmsg(cmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, cmsg); /* * Facility Request Parameter is not decoded by capi_message2cmsg() * encoding depends on Facility Selector */ - switch (iif->acmsg.FacilitySelector) { + switch (cmsg->FacilitySelector) { case CAPI_FACILITY_DTMF: /* ToDo */ info = CapiFacilityNotSupported; confparam[0] = 2; /* length */ @@ -1093,7 +1086,7 @@ static void do_facility_req(struct gigaset_capi_ctr *iif, case CAPI_FACILITY_SUPPSVC: /* decode Function parameter */ - pparam = iif->acmsg.FacilityRequestParameter; + pparam = cmsg->FacilityRequestParameter; if (pparam == NULL || *pparam < 2) { dev_notice(cs->dev, "%s: %s missing\n", "FACILITY_REQ", "Facility Request Parameter"); @@ -1141,18 +1134,18 @@ static void do_facility_req(struct gigaset_capi_ctr *iif, } /* send FACILITY_CONF with given Info and confirmation parameter */ - capi_cmsg_answer(&iif->acmsg); - iif->acmsg.Info = info; - iif->acmsg.FacilityConfirmationParameter = confparam; + capi_cmsg_answer(cmsg); + cmsg->Info = info; + cmsg->FacilityConfirmationParameter = confparam; msgsize += confparam[0]; /* length */ cskb = alloc_skb(msgsize, GFP_ATOMIC); if (!cskb) { dev_err(cs->dev, "%s: out of memory\n", __func__); return; } - capi_cmsg2message(&iif->acmsg, __skb_put(cskb, msgsize)); - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); - capi_ctr_handle_message(&iif->ctr, ap->id, cskb); + capi_cmsg2message(cmsg, __skb_put(cskb, msgsize)); + dump_cmsg(DEBUG_CMD, __func__, cmsg); + capi_ctr_handle_message(&iif->ctr, ap->id, cskb); } @@ -1207,8 +1200,8 @@ static void do_connect_req(struct gigaset_capi_ctr *iif, u16 info; /* decode message */ - capi_message2cmsg(&iif->acmsg, skb->data); - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + capi_message2cmsg(cmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, cmsg); /* get free B channel & construct PLCI */ bcs = gigaset_get_free_channel(cs); @@ -1411,8 +1404,16 @@ static void do_connect_req(struct gigaset_capi_ctr *iif, "CONNECT_REQ", "Calling pty subaddr"); ignore_cstruct_param(cs, cmsg->LLC, "CONNECT_REQ", "LLC"); - ignore_cmstruct_param(cs, cmsg->AdditionalInfo, - "CONNECT_REQ", "Additional Info"); + if (cmsg->AdditionalInfo != CAPI_DEFAULT) { + ignore_cstruct_param(cs, cmsg->BChannelinformation, + "CONNECT_REQ", "B Channel Information"); + ignore_cstruct_param(cs, cmsg->Keypadfacility, + "CONNECT_REQ", "Keypad Facility"); + ignore_cstruct_param(cs, cmsg->Useruserdata, + "CONNECT_REQ", "User-User Data"); + ignore_cstruct_param(cs, cmsg->Facilitydataarray, + "CONNECT_REQ", "Facility Data Array"); + } /* encode parameter: B channel to use */ commands[AT_ISO] = kmalloc(9, GFP_KERNEL); @@ -1458,8 +1459,8 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif, int channel; /* decode message */ - capi_message2cmsg(&iif->acmsg, skb->data); - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + capi_message2cmsg(cmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, cmsg); dev_kfree_skb(skb); /* extract and check channel number from PLCI */ @@ -1524,8 +1525,16 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif, "CONNECT_RESP", "Connected Subaddress"); ignore_cstruct_param(cs, cmsg->LLC, "CONNECT_RESP", "LLC"); - ignore_cmstruct_param(cs, cmsg->AdditionalInfo, - "CONNECT_RESP", "Additional Info"); + if (cmsg->AdditionalInfo != CAPI_DEFAULT) { + ignore_cstruct_param(cs, cmsg->BChannelinformation, + "CONNECT_RESP", "BChannel Information"); + ignore_cstruct_param(cs, cmsg->Keypadfacility, + "CONNECT_RESP", "Keypad Facility"); + ignore_cstruct_param(cs, cmsg->Useruserdata, + "CONNECT_RESP", "User-User Data"); + ignore_cstruct_param(cs, cmsg->Facilitydataarray, + "CONNECT_RESP", "Facility Data Array"); + } /* Accept call */ if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state, @@ -1587,17 +1596,18 @@ static void do_connect_b3_req(struct gigaset_capi_ctr *iif, struct sk_buff *skb) { struct cardstate *cs = iif->ctr.driverdata; + _cmsg *cmsg = &iif->acmsg; int channel; /* decode message */ - capi_message2cmsg(&iif->acmsg, skb->data); - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + capi_message2cmsg(cmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, cmsg); /* extract and check channel number from PLCI */ - channel = (iif->acmsg.adr.adrPLCI >> 8) & 0xff; + channel = (cmsg->adr.adrPLCI >> 8) & 0xff; if (!channel || channel > cs->channels) { dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", - "CONNECT_B3_REQ", "PLCI", iif->acmsg.adr.adrPLCI); + "CONNECT_B3_REQ", "PLCI", cmsg->adr.adrPLCI); send_conf(iif, ap, skb, CapiIllContrPlciNcci); return; } @@ -1606,14 +1616,12 @@ static void do_connect_b3_req(struct gigaset_capi_ctr *iif, ap->connected = APCONN_ACTIVE; /* build NCCI: always 1 (one B3 connection only) */ - iif->acmsg.adr.adrNCCI |= 1 << 16; + cmsg->adr.adrNCCI |= 1 << 16; /* NCPI parameter: not applicable for B3 Transparent */ - ignore_cstruct_param(cs, iif->acmsg.NCPI, - "CONNECT_B3_REQ", "NCPI"); - send_conf(iif, ap, skb, - (iif->acmsg.NCPI && iif->acmsg.NCPI[0]) ? - CapiNcpiNotSupportedByProtocol : CapiSuccess); + ignore_cstruct_param(cs, cmsg->NCPI, "CONNECT_B3_REQ", "NCPI"); + send_conf(iif, ap, skb, (cmsg->NCPI && cmsg->NCPI[0]) ? + CapiNcpiNotSupportedByProtocol : CapiSuccess); } /* @@ -1628,27 +1636,28 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif, struct sk_buff *skb) { struct cardstate *cs = iif->ctr.driverdata; - struct bc_state *bcs = NULL; + _cmsg *cmsg = &iif->acmsg; + struct bc_state *bcs; int channel; unsigned int msgsize; u8 command; /* decode message */ - capi_message2cmsg(&iif->acmsg, skb->data); - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + capi_message2cmsg(cmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, cmsg); /* extract and check channel number and NCCI */ - channel = (iif->acmsg.adr.adrNCCI >> 8) & 0xff; + channel = (cmsg->adr.adrNCCI >> 8) & 0xff; if (!channel || channel > cs->channels || - ((iif->acmsg.adr.adrNCCI >> 16) & 0xffff) != 1) { + ((cmsg->adr.adrNCCI >> 16) & 0xffff) != 1) { dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", - "CONNECT_B3_RESP", "NCCI", iif->acmsg.adr.adrNCCI); + "CONNECT_B3_RESP", "NCCI", cmsg->adr.adrNCCI); dev_kfree_skb(skb); return; } bcs = &cs->bcs[channel-1]; - if (iif->acmsg.Reject) { + if (cmsg->Reject) { /* Reject: clear B3 connect received flag */ ap->connected = APCONN_SETUP; @@ -1673,11 +1682,11 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif, command = CAPI_CONNECT_B3_ACTIVE; msgsize = CAPI_CONNECT_B3_ACTIVE_IND_BASELEN; } - capi_cmsg_header(&iif->acmsg, ap->id, command, CAPI_IND, - ap->nextMessageNumber++, iif->acmsg.adr.adrNCCI); + capi_cmsg_header(cmsg, ap->id, command, CAPI_IND, + ap->nextMessageNumber++, cmsg->adr.adrNCCI); __skb_trim(skb, msgsize); - capi_cmsg2message(&iif->acmsg, skb->data); - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + capi_cmsg2message(cmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, cmsg); capi_ctr_handle_message(&iif->ctr, ap->id, skb); } @@ -1691,28 +1700,37 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif, struct sk_buff *skb) { struct cardstate *cs = iif->ctr.driverdata; + _cmsg *cmsg = &iif->acmsg; struct bc_state *bcs; _cmsg *b3cmsg; struct sk_buff *b3skb; int channel; /* decode message */ - capi_message2cmsg(&iif->acmsg, skb->data); - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + capi_message2cmsg(cmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, cmsg); /* extract and check channel number from PLCI */ - channel = (iif->acmsg.adr.adrPLCI >> 8) & 0xff; + channel = (cmsg->adr.adrPLCI >> 8) & 0xff; if (!channel || channel > cs->channels) { dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", - "DISCONNECT_REQ", "PLCI", iif->acmsg.adr.adrPLCI); + "DISCONNECT_REQ", "PLCI", cmsg->adr.adrPLCI); send_conf(iif, ap, skb, CapiIllContrPlciNcci); return; } bcs = cs->bcs + channel - 1; /* ToDo: process parameter: Additional info */ - ignore_cmstruct_param(cs, iif->acmsg.AdditionalInfo, - "DISCONNECT_REQ", "Additional Info"); + if (cmsg->AdditionalInfo != CAPI_DEFAULT) { + ignore_cstruct_param(cs, cmsg->BChannelinformation, + "DISCONNECT_REQ", "B Channel Information"); + ignore_cstruct_param(cs, cmsg->Keypadfacility, + "DISCONNECT_REQ", "Keypad Facility"); + ignore_cstruct_param(cs, cmsg->Useruserdata, + "DISCONNECT_REQ", "User-User Data"); + ignore_cstruct_param(cs, cmsg->Facilitydataarray, + "DISCONNECT_REQ", "Facility Data Array"); + } /* skip if DISCONNECT_IND already sent */ if (!ap->connected) @@ -1733,7 +1751,7 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif, } capi_cmsg_header(b3cmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND, ap->nextMessageNumber++, - iif->acmsg.adr.adrPLCI | (1 << 16)); + cmsg->adr.adrPLCI | (1 << 16)); b3cmsg->Reason_B3 = CapiProtocolErrorLayer1; b3skb = alloc_skb(CAPI_DISCONNECT_B3_IND_BASELEN, GFP_KERNEL); if (b3skb == NULL) { @@ -1769,18 +1787,19 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif, struct sk_buff *skb) { struct cardstate *cs = iif->ctr.driverdata; + _cmsg *cmsg = &iif->acmsg; int channel; /* decode message */ - capi_message2cmsg(&iif->acmsg, skb->data); - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + capi_message2cmsg(cmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, cmsg); /* extract and check channel number and NCCI */ - channel = (iif->acmsg.adr.adrNCCI >> 8) & 0xff; + channel = (cmsg->adr.adrNCCI >> 8) & 0xff; if (!channel || channel > cs->channels || - ((iif->acmsg.adr.adrNCCI >> 16) & 0xffff) != 1) { + ((cmsg->adr.adrNCCI >> 16) & 0xffff) != 1) { dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", - "DISCONNECT_B3_REQ", "NCCI", iif->acmsg.adr.adrNCCI); + "DISCONNECT_B3_REQ", "NCCI", cmsg->adr.adrNCCI); send_conf(iif, ap, skb, CapiIllContrPlciNcci); return; } @@ -1803,11 +1822,10 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif, gigaset_schedule_event(cs); /* NCPI parameter: not applicable for B3 Transparent */ - ignore_cstruct_param(cs, iif->acmsg.NCPI, + ignore_cstruct_param(cs, cmsg->NCPI, "DISCONNECT_B3_REQ", "NCPI"); - send_conf(iif, ap, skb, - (iif->acmsg.NCPI && iif->acmsg.NCPI[0]) ? - CapiNcpiNotSupportedByProtocol : CapiSuccess); + send_conf(iif, ap, skb, (cmsg->NCPI && cmsg->NCPI[0]) ? + CapiNcpiNotSupportedByProtocol : CapiSuccess); } /* -- cgit v1.2.2 From 22077ebceb44f4097d4677e2a26bc1175143d647 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sun, 25 Oct 2009 09:29:47 +0000 Subject: gigaset: fix format string typo in CAPI dial command A missing dot lead to garbage characters being included in the dial command generated from a CAPI CONNECT_REQ message, which interestingly enough worked anyway, illustrating the resilience of the device. Impact: bugfix Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/capi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index ac0a2da1eef6..d1afac2bf650 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -1254,7 +1254,7 @@ static void do_connect_req(struct gigaset_capi_ctr *iif, commands[AT_DIAL] = kmalloc(l+3, GFP_KERNEL); if (!commands[AT_DIAL]) goto oom; - snprintf(commands[AT_DIAL], l+3, "D%*s\r", l, pp); + snprintf(commands[AT_DIAL], l+3, "D%.*s\r", l, pp); /* encode parameter: Calling party number */ pp = cmsg->CallingPartyNumber; -- cgit v1.2.2 From 4dd8230acd20cb456cae02696b3da2986faad258 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sun, 25 Oct 2009 09:29:57 +0000 Subject: gigaset: fix bad assumptions about CAPI skbuffs The CAPI interface incorrectly assumed that CAPI messages would always start at the beginning of the data buffer: fix by treating DATA_B3 messages as the link layer header to their payload data. This fix changes the way acknowledgement information is propagated through the hardware specific modules and thereby impacts the ISDN4Linux variant of the driver, too. Also some assumptions about methods not being called from interrupt context turned out to be unwarranted; fix by using dev_kfree_skb_any() wherever non-interrupt context isn't guaranteed. Impact: bugfix Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/asyncdata.c | 55 ++++++++++++++++++++++------------------ drivers/isdn/gigaset/capi.c | 29 +++++++++++---------- drivers/isdn/gigaset/gigaset.h | 2 +- drivers/isdn/gigaset/i4l.c | 28 ++++++++++++++------ drivers/isdn/gigaset/isocdata.c | 6 ++--- 5 files changed, 70 insertions(+), 50 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index a25216bf475e..256fc4809c81 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c @@ -156,7 +156,7 @@ byte_stuff: /* end of frame */ gigaset_isdn_rcv_err(bcs); - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); } else if (!(inputstate & INS_have_data)) { /* 7E 7E */ #ifdef CONFIG_GIGASET_DEBUG ++bcs->emptycount; @@ -172,7 +172,7 @@ byte_stuff: "Checksum failed, %u bytes corrupted!\n", skb->len); gigaset_isdn_rcv_err(bcs); - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); } else if (likely(skb->len > 2)) { __skb_trim(skb, skb->len - 2); gigaset_skb_rcvd(bcs, skb); @@ -182,7 +182,7 @@ byte_stuff: "invalid packet size (%d)\n", skb->len); gigaset_isdn_rcv_err(bcs); } - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); } } @@ -430,11 +430,11 @@ EXPORT_SYMBOL_GPL(gigaset_m10x_input); * opening and closing flags, preserving headroom data. * parameters: * 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 + * and the original link layer header, NULL on error */ -static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int headroom) +static struct sk_buff *HDLC_Encode(struct sk_buff *skb) { struct sk_buff *hdlc_skb; __u16 fcs; @@ -456,17 +456,19 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int headroom) /* 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 + * + room for link layer header */ - hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + headroom); + hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + skb->mac_len); if (!hdlc_skb) { - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); return NULL; } - /* Copy acknowledgement header into new skb */ - skb_reserve(hdlc_skb, headroom); - memcpy(hdlc_skb->head, skb->head, headroom); + /* Copy link layer header into new skb */ + skb_reset_mac_header(hdlc_skb); + skb_reserve(hdlc_skb, skb->mac_len); + memcpy(skb_mac_header(hdlc_skb), skb_mac_header(skb), skb->mac_len); + hdlc_skb->mac_len = skb->mac_len; /* Add flag sequence in front of everything.. */ *(skb_put(hdlc_skb, 1)) = PPP_FLAG; @@ -497,7 +499,7 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int headroom) *(skb_put(hdlc_skb, 1)) = PPP_FLAG; - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); return hdlc_skb; } @@ -506,28 +508,33 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int headroom) * preserving headroom data. * parameters: * 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 + * and the original link layer header, NULL on error */ -static struct sk_buff *iraw_encode(struct sk_buff *skb, int headroom) +static struct sk_buff *iraw_encode(struct sk_buff *skb) { 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 + headroom); + /* size of new buffer (worst case = every byte must be stuffed): + * 2 * original size + room for link layer header + */ + iraw_skb = dev_alloc_skb(2*skb->len + skb->mac_len); if (!iraw_skb) { - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); return NULL; } - /* Copy acknowledgement header into new skb */ - skb_reserve(iraw_skb, headroom); - memcpy(iraw_skb->head, skb->head, headroom); + /* copy link layer header into new skb */ + skb_reset_mac_header(iraw_skb); + skb_reserve(iraw_skb, skb->mac_len); + memcpy(skb_mac_header(iraw_skb), skb_mac_header(skb), skb->mac_len); + iraw_skb->mac_len = skb->mac_len; + /* copy and stuff data */ cp = skb->data; len = skb->len; while (len--) { @@ -536,7 +543,7 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int headroom) *(skb_put(iraw_skb, 1)) = c; *(skb_put(iraw_skb, 1)) = c; } - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); return iraw_skb; } @@ -548,7 +555,7 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int headroom) * 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. + * will be called with the skb's link layer header preserved. * * Return value: * number of bytes accepted for sending (skb->len) if ok, @@ -560,9 +567,9 @@ int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb) unsigned long flags; if (bcs->proto2 == L2_HDLC) - skb = HDLC_Encode(skb, bcs->cs->hw_hdr_len); + skb = HDLC_Encode(skb); else - skb = iraw_encode(skb, bcs->cs->hw_hdr_len); + skb = iraw_encode(skb); if (!skb) { dev_err(bcs->cs->dev, "unable to allocate memory for encoding!\n"); diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index d1afac2bf650..3f5cd06af104 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -362,6 +362,7 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb) struct cardstate *cs = bcs->cs; struct gigaset_capi_ctr *iif = cs->iif; struct gigaset_capi_appl *ap = bcs->ap; + unsigned char *req = skb_mac_header(dskb); struct sk_buff *cskb; u16 flags; @@ -380,7 +381,7 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb) } /* ToDo: honor unset "delivery confirmation" bit */ - flags = CAPIMSG_FLAGS(dskb->head); + flags = CAPIMSG_FLAGS(req); /* build DATA_B3_CONF message */ cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC); @@ -393,11 +394,11 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb) CAPIMSG_SETAPPID(cskb->data, ap->id); CAPIMSG_SETCOMMAND(cskb->data, CAPI_DATA_B3); CAPIMSG_SETSUBCOMMAND(cskb->data, CAPI_CONF); - CAPIMSG_SETMSGID(cskb->data, CAPIMSG_MSGID(dskb->head)); + CAPIMSG_SETMSGID(cskb->data, CAPIMSG_MSGID(req)); CAPIMSG_SETCONTROLLER(cskb->data, iif->ctr.cnr); CAPIMSG_SETPLCI_PART(cskb->data, bcs->channel + 1); CAPIMSG_SETNCCI_PART(cskb->data, 1); - CAPIMSG_SETHANDLE_CONF(cskb->data, CAPIMSG_HANDLE_REQ(dskb->head)); + CAPIMSG_SETHANDLE_CONF(cskb->data, CAPIMSG_HANDLE_REQ(req)); if (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION) CAPIMSG_SETINFO_CONF(cskb->data, CapiFlagsNotSupportedByProtocol); @@ -437,7 +438,7 @@ void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb) /* don't send further B3 messages if disconnected */ if (ap->connected < APCONN_ACTIVE) { gig_dbg(DEBUG_LLDATA, "disconnected, discarding data"); - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); return; } @@ -1461,7 +1462,7 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif, /* decode message */ capi_message2cmsg(cmsg, skb->data); dump_cmsg(DEBUG_CMD, __func__, cmsg); - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); /* extract and check channel number from PLCI */ channel = (cmsg->adr.adrPLCI >> 8) & 0xff; @@ -1652,7 +1653,7 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif, ((cmsg->adr.adrNCCI >> 16) & 0xffff) != 1) { dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", "CONNECT_B3_RESP", "NCCI", cmsg->adr.adrNCCI); - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); return; } bcs = &cs->bcs[channel-1]; @@ -1665,7 +1666,7 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif, if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) { dev_err(cs->dev, "%s: out of memory\n", __func__); - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); return; } gig_dbg(DEBUG_CMD, "scheduling HUP"); @@ -1880,12 +1881,12 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif, return; } - /* - * pull CAPI message from skb, - * pass payload data to device-specific module - * CAPI message will be preserved in headroom - */ + /* pull CAPI message into link layer header */ + skb_reset_mac_header(skb); + skb->mac_len = msglen; skb_pull(skb, msglen); + + /* pass to device-specific module */ if (cs->ops->send_skb(&cs->bcs[channel-1], skb) < 0) { send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); return; @@ -1946,7 +1947,7 @@ static void do_nothing(struct gigaset_capi_ctr *iif, capi_message2cmsg(&iif->acmsg, skb->data); dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); } - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); } static void do_data_b3_resp(struct gigaset_capi_ctr *iif, @@ -1954,7 +1955,7 @@ static void do_data_b3_resp(struct gigaset_capi_ctr *iif, struct sk_buff *skb) { dump_rawmsg(DEBUG_LLDATA, __func__, skb->data); - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); } /* table of outgoing CAPI message handlers with lookup function */ diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 4749ef100fd3..c59216b9c1d0 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -625,7 +625,7 @@ struct gigaset_ops { /* Called from LL interface to put an skb into the send-queue. * After sending is completed, gigaset_skb_sent() must be called - * with the first cs->hw_hdr_len bytes of skb->head preserved. */ + * with the skb's link layer header preserved. */ int (*send_skb)(struct bc_state *bcs, struct sk_buff *skb); /* Called from ev-layer.c to process a block of data diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c index aca72a06184e..828824f905c4 100644 --- a/drivers/isdn/gigaset/i4l.c +++ b/drivers/isdn/gigaset/i4l.c @@ -41,8 +41,8 @@ static int writebuf_from_LL(int driverID, int channel, int ack, { struct cardstate *cs; struct bc_state *bcs; + unsigned char *ack_header; unsigned len; - unsigned skblen; if (!(cs = gigaset_get_cs_by_id(driverID))) { pr_err("%s: invalid driver ID (%d)\n", __func__, driverID); @@ -78,11 +78,23 @@ static int writebuf_from_LL(int driverID, int channel, int ack, return -EINVAL; } - skblen = ack ? len : 0; - skb->head[0] = skblen & 0xff; - skb->head[1] = skblen >> 8; - gig_dbg(DEBUG_MCMD, "skb: len=%u, skblen=%u: %02x %02x", - len, skblen, (unsigned) skb->head[0], (unsigned) skb->head[1]); + /* set up acknowledgement header */ + if (skb_headroom(skb) < HW_HDR_LEN) { + /* should never happen */ + dev_err(cs->dev, "%s: insufficient skb headroom\n", __func__); + return -ENOMEM; + } + skb_set_mac_header(skb, -HW_HDR_LEN); + skb->mac_len = HW_HDR_LEN; + ack_header = skb_mac_header(skb); + if (ack) { + ack_header[0] = len & 0xff; + ack_header[1] = len >> 8; + } else { + ack_header[0] = ack_header[1] = 0; + } + gig_dbg(DEBUG_MCMD, "skb: len=%u, ack=%d: %02x %02x", + len, ack, ack_header[0], ack_header[1]); /* pass to device-specific module */ return cs->ops->send_skb(bcs, skb); @@ -99,6 +111,7 @@ static int writebuf_from_LL(int driverID, int channel, int ack, void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) { isdn_if *iif = bcs->cs->iif; + unsigned char *ack_header = skb_mac_header(skb); unsigned len; isdn_ctrl response; @@ -108,8 +121,7 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) dev_warn(bcs->cs->dev, "%s: skb->len==%d\n", __func__, skb->len); - len = (unsigned char) skb->head[0] | - (unsigned) (unsigned char) skb->head[1] << 8; + len = ack_header[0] + ((unsigned) ack_header[1] << 8); if (len) { gig_dbg(DEBUG_MCMD, "ACKing to LL (id: %d, ch: %d, sz: %u)", bcs->cs->myid, bcs->channel, len); diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index 7dabfd35874c..bc41611e541d 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c @@ -576,12 +576,12 @@ static inline void hdlc_done(struct bc_state *bcs) dev_notice(cs->dev, "received short frame (%d octets)\n", procskb->len); bcs->hw.bas->runts++; - dev_kfree_skb(procskb); + dev_kfree_skb_any(procskb); gigaset_isdn_rcv_err(bcs); } else if (bcs->fcs != PPP_GOODFCS) { dev_notice(cs->dev, "frame check error (0x%04x)\n", bcs->fcs); bcs->hw.bas->fcserrs++; - dev_kfree_skb(procskb); + dev_kfree_skb_any(procskb); gigaset_isdn_rcv_err(bcs); } else { len = procskb->len; @@ -985,7 +985,7 @@ void gigaset_isoc_input(struct inbuf_t *inbuf) * Called by LL to 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. + * will be called with the skb's link layer header preserved. * * Return value: * number of bytes accepted for sending (skb->len) if ok, -- cgit v1.2.2 From 2032e2c2309de02cd67b1d26aa701c2a57c4639f Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sun, 25 Oct 2009 09:30:07 +0000 Subject: usb_gigaset: code cleanup Reorganize the code of the Gigaset M10x driver to make it more readable, less redundant, better aligned to the style of other parts of the driver, and cause fewer checkpatch.pl complaints. Impact: code reorganization, no functional change Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/asyncdata.c | 573 ++++++++++++++++++++----------------- drivers/isdn/gigaset/common.c | 34 +-- drivers/isdn/gigaset/gigaset.h | 13 +- drivers/isdn/gigaset/usb-gigaset.c | 69 +++-- 4 files changed, 358 insertions(+), 331 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index 256fc4809c81..ccb2a7b7c41d 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c @@ -19,7 +19,7 @@ /* check if byte must be stuffed/escaped * I'm not sure which data should be encoded. - * Therefore I will go the hard way and decode every value + * Therefore I will go the hard way and encode every value * less than 0x20, the flag sequence and the control escape char. */ static inline int muststuff(unsigned char c) @@ -35,288 +35,383 @@ static inline int muststuff(unsigned char c) /* == data input =========================================================== */ -/* process a block of received bytes in command mode (modem response) +/* process a block of received bytes in command mode + * (mstate != MS_LOCKED && (inputstate & INS_command)) + * Append received bytes to the command response buffer and forward them + * line by line to the response handler. Exit whenever a mode/state change + * might have occurred. * Return value: * number of processed bytes */ -static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes, - struct inbuf_t *inbuf) +static unsigned cmd_loop(unsigned numbytes, struct inbuf_t *inbuf) { + unsigned char *src = inbuf->data + inbuf->head; struct cardstate *cs = inbuf->cs; - unsigned cbytes = cs->cbytes; - int inputstate = inbuf->inputstate; - int startbytes = numbytes; - - for (;;) { - cs->respdata[cbytes] = c; - if (c == 10 || c == 13) { - gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)", + unsigned cbytes = cs->cbytes; + unsigned procbytes = 0; + unsigned char c; + + while (procbytes < numbytes) { + c = *src++; + procbytes++; + + switch (c) { + case '\n': + if (cbytes == 0 && cs->respdata[0] == '\r') { + /* collapse LF with preceding CR */ + cs->respdata[0] = 0; + break; + } + /* --v-- fall through --v-- */ + case '\r': + /* end of message line, pass to response handler */ + gig_dbg(DEBUG_TRANSCMD, "%s: End of Message (%d Bytes)", __func__, cbytes); + if (cbytes >= MAX_RESP_SIZE) { + dev_warn(cs->dev, "response too large (%d)\n", + cbytes); + cbytes = MAX_RESP_SIZE; + } cs->cbytes = cbytes; - gigaset_handle_modem_response(cs); /* can change - cs->dle */ + gigaset_handle_modem_response(cs); cbytes = 0; - if (cs->dle && - !(inputstate & INS_DLE_command)) { - inputstate &= ~INS_command; - break; - } - } else { - /* advance in line buffer, checking for overflow */ - if (cbytes < MAX_RESP_SIZE - 1) - cbytes++; - else - dev_warn(cs->dev, "response too large\n"); - } + /* store EOL byte for CRLF collapsing */ + cs->respdata[0] = c; - if (!numbytes) - break; - c = *src++; - --numbytes; - if (c == DLE_FLAG && - (cs->dle || inputstate & INS_DLE_command)) { - inputstate |= INS_DLE_char; - break; + /* cs->dle may have changed */ + if (cs->dle && !(inbuf->inputstate & INS_DLE_command)) + inbuf->inputstate &= ~INS_command; + + /* return for reevaluating state */ + goto exit; + + case DLE_FLAG: + if (inbuf->inputstate & INS_DLE_char) { + /* quoted DLE: clear quote flag */ + inbuf->inputstate &= ~INS_DLE_char; + } else if (cs->dle || + (inbuf->inputstate & INS_DLE_command)) { + /* DLE escape, pass up for handling */ + inbuf->inputstate |= INS_DLE_char; + goto exit; + } + /* quoted or not in DLE mode: treat as regular data */ + /* --v-- fall through --v-- */ + default: + /* append to line buffer if possible */ + if (cbytes < MAX_RESP_SIZE) + cs->respdata[cbytes] = c; + cbytes++; } } - +exit: cs->cbytes = cbytes; - inbuf->inputstate = inputstate; - - return startbytes - numbytes; + return procbytes; } -/* process a block of received bytes in lock mode (tty i/f) +/* process a block of received bytes in lock mode + * All received bytes are passed unmodified to the tty i/f. * Return value: * number of processed bytes */ -static inline int lock_loop(unsigned char *src, int numbytes, - struct inbuf_t *inbuf) +static unsigned lock_loop(unsigned numbytes, struct inbuf_t *inbuf) { - struct cardstate *cs = inbuf->cs; - - gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", - numbytes, src); - gigaset_if_receive(cs, src, numbytes); + unsigned char *src = inbuf->data + inbuf->head; + gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", numbytes, src); + gigaset_if_receive(inbuf->cs, src, 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 + * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 == L2_HDLC) * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes. * When a frame is complete, check the FCS and pass valid frames to the LL. * If DLE is encountered, return immediately to let the caller handle it. * Return value: * number of processed bytes - * numbytes (all bytes processed) on error --FIXME */ -static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes, - struct inbuf_t *inbuf) +static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf) { struct cardstate *cs = inbuf->cs; - struct bc_state *bcs = inbuf->bcs; + struct bc_state *bcs = cs->bcs; int inputstate = bcs->inputstate; __u16 fcs = bcs->fcs; struct sk_buff *skb = bcs->skb; - int startbytes = numbytes; + unsigned char *src = inbuf->data + inbuf->head; + unsigned procbytes = 0; + unsigned char c; - if (unlikely(inputstate & INS_byte_stuff)) { + if (inputstate & INS_byte_stuff) { + if (!numbytes) + return 0; inputstate &= ~INS_byte_stuff; goto byte_stuff; } - for (;;) { - if (unlikely(c == PPP_ESCAPE)) { - if (unlikely(!numbytes)) { - inputstate |= INS_byte_stuff; + + while (procbytes < numbytes) { + c = *src++; + procbytes++; + if (c == DLE_FLAG) { + if (inputstate & INS_DLE_char) { + /* quoted DLE: clear quote flag */ + inputstate &= ~INS_DLE_char; + } else if (cs->dle || (inputstate & INS_DLE_command)) { + /* DLE escape, pass up for handling */ + inputstate |= INS_DLE_char; break; } - c = *src++; - --numbytes; - if (unlikely(c == DLE_FLAG && - (cs->dle || - inbuf->inputstate & INS_DLE_command))) { - inbuf->inputstate |= INS_DLE_char; + } + + if (c == PPP_ESCAPE) { + /* byte stuffing indicator: pull in next byte */ + if (procbytes >= numbytes) { + /* end of buffer, save for later processing */ inputstate |= INS_byte_stuff; break; } byte_stuff: + c = *src++; + procbytes++; + if (c == DLE_FLAG) { + if (inputstate & INS_DLE_char) { + /* quoted DLE: clear quote flag */ + inputstate &= ~INS_DLE_char; + } else if (cs->dle || + (inputstate & INS_DLE_command)) { + /* DLE escape, pass up for handling */ + inputstate |= + INS_DLE_char | INS_byte_stuff; + break; + } + } c ^= PPP_TRANS; - if (unlikely(!muststuff(c))) - gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c); - } else if (unlikely(c == PPP_FLAG)) { - if (unlikely(inputstate & INS_skip_frame)) { #ifdef CONFIG_GIGASET_DEBUG - if (!(inputstate & INS_have_data)) { /* 7E 7E */ - ++bcs->emptycount; - } else - gig_dbg(DEBUG_HDLC, - "7e----------------------------"); -#endif - - /* end of frame */ - gigaset_isdn_rcv_err(bcs); - dev_kfree_skb_any(skb); - } else if (!(inputstate & INS_have_data)) { /* 7E 7E */ -#ifdef CONFIG_GIGASET_DEBUG - ++bcs->emptycount; + if (!muststuff(c)) + gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c); #endif - break; - } else { + } else if (c == PPP_FLAG) { + /* end of frame: process content if any */ + if (inputstate & INS_have_data) { gig_dbg(DEBUG_HDLC, "7e----------------------------"); - /* end of frame */ - if (unlikely(fcs != PPP_GOODFCS)) { + /* check and pass received frame */ + if (!skb) { + /* skipped frame */ + gigaset_isdn_rcv_err(bcs); + } else if (skb->len < 2) { + /* frame too short for FCS */ + dev_warn(cs->dev, + "short frame (%d)\n", + skb->len); + gigaset_isdn_rcv_err(bcs); + dev_kfree_skb_any(skb); + } else if (fcs != PPP_GOODFCS) { + /* frame check error */ dev_err(cs->dev, "Checksum failed, %u bytes corrupted!\n", skb->len); gigaset_isdn_rcv_err(bcs); dev_kfree_skb_any(skb); - } else if (likely(skb->len > 2)) { + } else { + /* good frame */ __skb_trim(skb, skb->len - 2); gigaset_skb_rcvd(bcs, skb); - } else { - if (skb->len) { - dev_err(cs->dev, - "invalid packet size (%d)\n", skb->len); - gigaset_isdn_rcv_err(bcs); - } - dev_kfree_skb_any(skb); } - } - fcs = PPP_INITFCS; - inputstate &= ~(INS_have_data | INS_skip_frame); - if (unlikely(bcs->ignore)) { - inputstate |= INS_skip_frame; - skb = NULL; + /* prepare reception of next frame */ + inputstate &= ~INS_have_data; + new_rcv_skb(bcs); + skb = bcs->skb; } else { - 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; + /* empty frame (7E 7E) */ +#ifdef CONFIG_GIGASET_DEBUG + ++bcs->emptycount; +#endif + if (!skb) { + /* skipped (?) */ + gigaset_isdn_rcv_err(bcs); + new_rcv_skb(bcs); + skb = bcs->skb; } } - break; - } else if (unlikely(muststuff(c))) { + fcs = PPP_INITFCS; + continue; +#ifdef CONFIG_GIGASET_DEBUG + } else if (muststuff(c)) { /* Should not happen. Possible after ZDLE=1. */ gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c); +#endif } - /* add character */ - + /* regular data byte, append to skb */ #ifdef CONFIG_GIGASET_DEBUG - if (unlikely(!(inputstate & INS_have_data))) { + if (!(inputstate & INS_have_data)) { gig_dbg(DEBUG_HDLC, "7e (%d x) ================", bcs->emptycount); bcs->emptycount = 0; } #endif - inputstate |= INS_have_data; - - if (likely(!(inputstate & INS_skip_frame))) { - if (unlikely(skb->len == SBUFSIZE)) { + if (skb) { + if (skb->len == SBUFSIZE) { dev_warn(cs->dev, "received packet too long\n"); dev_kfree_skb_any(skb); - skb = NULL; - inputstate |= INS_skip_frame; - break; + /* skip remainder of packet */ + bcs->skb = skb = NULL; + } else { + *__skb_put(skb, 1) = c; + fcs = crc_ccitt_byte(fcs, c); } - *__skb_put(skb, 1) = c; - fcs = crc_ccitt_byte(fcs, c); - } - - if (unlikely(!numbytes)) - break; - c = *src++; - --numbytes; - if (unlikely(c == DLE_FLAG && - (cs->dle || - inbuf->inputstate & INS_DLE_command))) { - inbuf->inputstate |= INS_DLE_char; - break; } } + bcs->inputstate = inputstate; bcs->fcs = fcs; - bcs->skb = skb; - return startbytes - numbytes; + return procbytes; } /* process a block of received bytes in transparent data mode + * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 != L2_HDLC) * Invert bytes, undoing byte stuffing and watching for DLE escapes. * If DLE is encountered, return immediately to let the caller handle it. * Return value: * number of processed bytes - * numbytes (all bytes processed) on error --FIXME */ -static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes, - struct inbuf_t *inbuf) +static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf) { struct cardstate *cs = inbuf->cs; - struct bc_state *bcs = inbuf->bcs; + struct bc_state *bcs = cs->bcs; int inputstate = bcs->inputstate; struct sk_buff *skb = bcs->skb; - int startbytes = numbytes; + unsigned char *src = inbuf->data + inbuf->head; + unsigned procbytes = 0; + unsigned char c; - for (;;) { - /* add character */ - inputstate |= INS_have_data; + if (!skb) { + /* skip this block */ + new_rcv_skb(bcs); + return numbytes; + } - if (likely(!(inputstate & INS_skip_frame))) { - if (unlikely(skb->len == SBUFSIZE)) { - //FIXME just pass skb up and allocate a new one - dev_warn(cs->dev, "received packet too long\n"); - dev_kfree_skb_any(skb); - skb = NULL; - inputstate |= INS_skip_frame; + while (procbytes < numbytes && skb->len < SBUFSIZE) { + c = *src++; + procbytes++; + + if (c == DLE_FLAG) { + if (inputstate & INS_DLE_char) { + /* quoted DLE: clear quote flag */ + inputstate &= ~INS_DLE_char; + } else if (cs->dle || (inputstate & INS_DLE_command)) { + /* DLE escape, pass up for handling */ + inputstate |= INS_DLE_char; break; } - *__skb_put(skb, 1) = bitrev8(c); } - if (unlikely(!numbytes)) - break; - c = *src++; - --numbytes; - if (unlikely(c == DLE_FLAG && - (cs->dle || - inbuf->inputstate & INS_DLE_command))) { - inbuf->inputstate |= INS_DLE_char; - break; - } + /* regular data byte: append to current skb */ + inputstate |= INS_have_data; + *__skb_put(skb, 1) = bitrev8(c); } /* pass data up */ - if (likely(inputstate & INS_have_data)) { - if (likely(!(inputstate & INS_skip_frame))) { - gigaset_skb_rcvd(bcs, skb); - } - inputstate &= ~(INS_have_data | INS_skip_frame); - if (unlikely(bcs->ignore)) { - inputstate |= INS_skip_frame; - skb = NULL; - } else { - 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; + if (inputstate & INS_have_data) { + gigaset_skb_rcvd(bcs, skb); + inputstate &= ~INS_have_data; + new_rcv_skb(bcs); + } + + bcs->inputstate = inputstate; + return procbytes; +} + +/* process DLE escapes + * Called whenever a DLE sequence might be encountered in the input stream. + * Either processes the entire DLE sequence or, if that isn't possible, + * notes the fact that an initial DLE has been received in the INS_DLE_char + * inputstate flag and resumes processing of the sequence on the next call. + */ +static void handle_dle(struct inbuf_t *inbuf) +{ + struct cardstate *cs = inbuf->cs; + + if (cs->mstate == MS_LOCKED) + return; /* no DLE processing in lock mode */ + + if (!(inbuf->inputstate & INS_DLE_char)) { + /* no DLE pending */ + if (inbuf->data[inbuf->head] == DLE_FLAG && + (cs->dle || inbuf->inputstate & INS_DLE_command)) { + /* start of DLE sequence */ + inbuf->head++; + if (inbuf->head == inbuf->tail || + inbuf->head == RBUFSIZE) { + /* end of buffer, save for later processing */ + inbuf->inputstate |= INS_DLE_char; + return; } + } else { + /* regular data byte */ + return; } } - bcs->inputstate = inputstate; - bcs->skb = skb; - return startbytes - numbytes; + /* consume pending DLE */ + inbuf->inputstate &= ~INS_DLE_char; + + switch (inbuf->data[inbuf->head]) { + case 'X': /* begin of event message */ + if (inbuf->inputstate & INS_command) + dev_notice(cs->dev, + "received X in command mode\n"); + inbuf->inputstate |= INS_command | INS_DLE_command; + inbuf->head++; /* byte consumed */ + break; + case '.': /* end of event message */ + if (!(inbuf->inputstate & INS_DLE_command)) + dev_notice(cs->dev, + "received . without X\n"); + inbuf->inputstate &= ~INS_DLE_command; + /* return to data mode if in DLE mode */ + if (cs->dle) + inbuf->inputstate &= ~INS_command; + inbuf->head++; /* byte consumed */ + break; + case DLE_FLAG: /* DLE in data stream */ + /* mark as quoted */ + inbuf->inputstate |= INS_DLE_char; + if (!(cs->dle || inbuf->inputstate & INS_DLE_command)) + dev_notice(cs->dev, + "received not in DLE mode\n"); + break; /* quoted byte left in buffer */ + default: + dev_notice(cs->dev, "received <%02x>\n", + inbuf->data[inbuf->head]); + /* quoted byte left in buffer */ + } } /** @@ -330,94 +425,39 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes, */ void gigaset_m10x_input(struct inbuf_t *inbuf) { - struct cardstate *cs; - unsigned tail, head, numbytes; - unsigned char *src, c; - int procbytes; - - head = inbuf->head; - tail = inbuf->tail; - gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); - - if (head != tail) { - cs = inbuf->cs; - src = inbuf->data + head; - numbytes = (head > tail ? RBUFSIZE : tail) - head; - gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); + struct cardstate *cs = inbuf->cs; + unsigned numbytes, procbytes; - while (numbytes) { - if (cs->mstate == MS_LOCKED) { - procbytes = lock_loop(src, numbytes, inbuf); - src += procbytes; - numbytes -= procbytes; - } else { - c = *src++; - --numbytes; - if (c == DLE_FLAG && (cs->dle || - inbuf->inputstate & INS_DLE_command)) { - if (!(inbuf->inputstate & INS_DLE_char)) { - inbuf->inputstate |= INS_DLE_char; - goto nextbyte; - } - /* => in data stream */ - inbuf->inputstate &= ~INS_DLE_char; - } + gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", inbuf->head, inbuf->tail); - if (!(inbuf->inputstate & INS_DLE_char)) { - - /* FIXME use function pointers? */ - if (inbuf->inputstate & INS_command) - procbytes = cmd_loop(c, src, numbytes, inbuf); - else if (inbuf->bcs->proto2 == L2_HDLC) - procbytes = hdlc_loop(c, src, numbytes, inbuf); - else - procbytes = iraw_loop(c, src, numbytes, inbuf); - - src += procbytes; - numbytes -= procbytes; - } else { /* DLE char */ - inbuf->inputstate &= ~INS_DLE_char; - switch (c) { - case 'X': /*begin of command*/ - if (inbuf->inputstate & INS_command) - dev_warn(cs->dev, - "received 'X' in command mode\n"); - inbuf->inputstate |= - INS_command | INS_DLE_command; - break; - case '.': /*end of command*/ - if (!(inbuf->inputstate & INS_command)) - dev_warn(cs->dev, - "received '.' in hdlc mode\n"); - inbuf->inputstate &= cs->dle ? - ~(INS_DLE_command|INS_command) - : ~INS_DLE_command; - break; - //case DLE_FLAG: /*DLE_FLAG in data stream*/ /* schon oben behandelt! */ - default: - dev_err(cs->dev, - "received 0x10 0x%02x!\n", - (int) c); - /* FIXME: reset driver?? */ - } - } - } -nextbyte: - if (!numbytes) { - /* end of buffer, check for wrap */ - if (head > tail) { - head = 0; - src = inbuf->data; - numbytes = tail; - } else { - head = tail; - break; - } - } - } + while (inbuf->head != inbuf->tail) { + /* check for DLE escape */ + handle_dle(inbuf); - gig_dbg(DEBUG_INTR, "setting head to %u", head); - inbuf->head = head; + /* process a contiguous block of bytes */ + numbytes = (inbuf->head > inbuf->tail ? + RBUFSIZE : inbuf->tail) - inbuf->head; + gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); + /* + * numbytes may be 0 if handle_dle() ate the last byte. + * This does no harm, *_loop() will just return 0 immediately. + */ + + if (cs->mstate == MS_LOCKED) + procbytes = lock_loop(numbytes, inbuf); + else if (inbuf->inputstate & INS_command) + procbytes = cmd_loop(numbytes, inbuf); + else if (cs->bcs->proto2 == L2_HDLC) + procbytes = hdlc_loop(numbytes, inbuf); + else + procbytes = iraw_loop(numbytes, inbuf); + inbuf->head += procbytes; + + /* check for buffer wraparound */ + if (inbuf->head >= RBUFSIZE) + inbuf->head = 0; + + gig_dbg(DEBUG_INTR, "head set to %u", inbuf->head); } } EXPORT_SYMBOL_GPL(gigaset_m10x_input); @@ -563,6 +603,7 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb) */ int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb) { + struct cardstate *cs = bcs->cs; unsigned len = skb->len; unsigned long flags; @@ -571,16 +612,16 @@ int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb) else skb = iraw_encode(skb); if (!skb) { - dev_err(bcs->cs->dev, + dev_err(cs->dev, "unable to allocate memory for encoding!\n"); return -ENOMEM; } skb_queue_tail(&bcs->squeue, skb); - spin_lock_irqsave(&bcs->cs->lock, flags); - if (bcs->cs->connected) - tasklet_schedule(&bcs->cs->write_tasklet); - spin_unlock_irqrestore(&bcs->cs->lock, flags); + spin_lock_irqsave(&cs->lock, flags); + if (cs->connected) + tasklet_schedule(&cs->write_tasklet); + spin_unlock_irqrestore(&cs->lock, flags); return len; /* ok so far */ } diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 1d2ae2e05e0b..690ac74c82a8 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -400,9 +400,9 @@ static void gigaset_freebcs(struct bc_state *bcs) gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel); clear_at_state(&bcs->at_state); gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel); + dev_kfree_skb(bcs->skb); + bcs->skb = NULL; - if (bcs->skb) - dev_kfree_skb(bcs->skb); for (i = 0; i < AT_NUM; ++i) { kfree(bcs->commands[i]); bcs->commands[i] = NULL; @@ -560,16 +560,13 @@ void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, } -static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs, - struct cardstate *cs, int inputstate) +static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct cardstate *cs) /* inbuf->read must be allocated before! */ { inbuf->head = 0; inbuf->tail = 0; inbuf->cs = cs; - inbuf->bcs = bcs; /*base driver: NULL*/ - inbuf->rcvbuf = NULL; - inbuf->inputstate = inputstate; + inbuf->inputstate = INS_command; } /** @@ -644,16 +641,13 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, bcs->fcs = PPP_INITFCS; bcs->inputstate = 0; if (cs->ignoreframes) { - bcs->inputstate |= INS_skip_frame; 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 { + else pr_err("out of memory\n"); - bcs->inputstate |= INS_skip_frame; - } } bcs->channel = channel; @@ -674,8 +668,8 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, gig_dbg(DEBUG_INIT, " failed"); gig_dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel); - if (bcs->skb) - dev_kfree_skb(bcs->skb); + dev_kfree_skb(bcs->skb); + bcs->skb = NULL; return NULL; } @@ -764,10 +758,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, cs->cbytes = 0; gig_dbg(DEBUG_INIT, "setting up inbuf"); - if (onechannel) { //FIXME distinction necessary? - gigaset_inbuf_init(cs->inbuf, cs->bcs, cs, INS_command); - } else - gigaset_inbuf_init(cs->inbuf, NULL, cs, INS_command); + gigaset_inbuf_init(cs->inbuf, cs); cs->connected = 0; cs->isdn_up = 0; @@ -854,9 +845,10 @@ void gigaset_bcs_reinit(struct bc_state *bcs) bcs->chstate = 0; bcs->ignore = cs->ignoreframes; - if (bcs->ignore) - bcs->inputstate |= INS_skip_frame; - + if (bcs->ignore) { + dev_kfree_skb(bcs->skb); + bcs->skb = NULL; + } cs->ops->reinitbcshw(bcs); } @@ -877,8 +869,6 @@ static void cleanup_cs(struct cardstate *cs) free_strings(&cs->at_state); gigaset_at_init(&cs->at_state, NULL, cs, 0); - kfree(cs->inbuf->rcvbuf); - cs->inbuf->rcvbuf = NULL; cs->inbuf->inputstate = INS_command; cs->inbuf->head = 0; cs->inbuf->tail = 0; diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index c59216b9c1d0..18bff9f80727 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -223,12 +223,11 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, #define EV_BC_CLOSED -118 /* input state */ -#define INS_command 0x0001 -#define INS_DLE_char 0x0002 +#define INS_command 0x0001 /* receiving messages (not payload data) */ +#define INS_DLE_char 0x0002 /* DLE flag received (in DLE mode) */ #define INS_byte_stuff 0x0004 #define INS_have_data 0x0008 -#define INS_skip_frame 0x0010 -#define INS_DLE_command 0x0020 +#define INS_DLE_command 0x0020 /* DLE message start ( X) received */ #define INS_flag_hunt 0x0040 /* channel state */ @@ -290,8 +289,6 @@ extern struct reply_t gigaset_tab_cid[]; extern struct reply_t gigaset_tab_nocid[]; struct inbuf_t { - unsigned char *rcvbuf; /* usb-gigaset receive buffer */ - struct bc_state *bcs; struct cardstate *cs; int inputstate; int head, tail; @@ -483,8 +480,8 @@ struct cardstate { struct timer_list timer; int retry_count; - int dle; /* !=0 if modem commands/responses are - dle encoded */ + int dle; /* !=0 if DLE mode is active + (ZDLE=1 received -- M10x only) */ int cur_at_seq; /* sequence of AT commands being processed */ int curchannel; /* channel those commands are meant diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index 4deb1ab0dbf8..f56b2a83793e 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c @@ -43,14 +43,14 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode"); #define GIGASET_MODULENAME "usb_gigaset" #define GIGASET_DEVNAME "ttyGU" -#define IF_WRITEBUF 2000 //FIXME // WAKEUP_CHARS: 256 +#define IF_WRITEBUF 2000 /* arbitrary limit */ /* Values for the Gigaset M105 Data */ #define USB_M105_VENDOR_ID 0x0681 #define USB_M105_PRODUCT_ID 0x0009 /* table of devices that work with this driver */ -static const struct usb_device_id gigaset_table [] = { +static const struct usb_device_id gigaset_table[] = { { USB_DEVICE(USB_M105_VENDOR_ID, USB_M105_PRODUCT_ID) }, { } /* Terminating entry */ }; @@ -97,8 +97,8 @@ MODULE_DEVICE_TABLE(usb, gigaset_table); * 41 19 -- -- -- -- 06 00 00 00 00 xx 11 13 * Used after every "configuration sequence" (RQ 12, RQs 01/03/13). * xx is usually 0x00 but was 0x7e before starting data transfer - * in unimodem mode. So, this might be an array of characters that need - * special treatment ("commit all bufferd data"?), 11=^Q, 13=^S. + * in unimodem mode. So, this might be an array of characters that + * need special treatment ("commit all bufferd data"?), 11=^Q, 13=^S. * * Unimodem mode: use "modprobe ppp_async flag_time=0" as the device _needs_ two * flags per packet. @@ -114,7 +114,7 @@ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message); static int gigaset_resume(struct usb_interface *intf); static int gigaset_pre_reset(struct usb_interface *intf); -static struct gigaset_driver *driver = NULL; +static struct gigaset_driver *driver; /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver gigaset_usb_driver = { @@ -141,6 +141,7 @@ struct usb_cardstate { struct urb *bulk_out_urb; /* Input buffer */ + unsigned char *rcvbuf; int rcvbuf_size; struct urb *read_urb; __u8 int_in_endpointAddr; @@ -164,13 +165,11 @@ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, val = tiocm_to_gigaset(new_state); gig_dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask); - // don't use this in an interrupt/BH r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 7, 0x41, (val & 0xff) | ((mask & 0xff) << 8), 0, NULL, 0, 2000 /* timeout? */); if (r < 0) return r; - //.. return 0; } @@ -220,7 +219,6 @@ static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag) cflag &= CBAUD; switch (cflag) { - //FIXME more values? case B300: rate = 300; break; case B600: rate = 600; break; case B1200: rate = 1200; break; @@ -273,7 +271,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) /* set the number of stop bits */ if (cflag & CSTOPB) { if ((cflag & CSIZE) == CS5) - val |= 1; /* 1.5 stop bits */ //FIXME is this okay? + val |= 1; /* 1.5 stop bits */ else val |= 2; /* 2 stop bits */ } @@ -282,7 +280,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) } - /*================================================================================================================*/ +/*============================================================================*/ static int gigaset_init_bchannel(struct bc_state *bcs) { /* nothing to do for M10x */ @@ -344,7 +342,6 @@ static void gigaset_modem_fill(unsigned long data) if (write_modem(cs) < 0) { gig_dbg(DEBUG_OUTPUT, "modem_fill: write_modem failed"); - // FIXME should we tell the LL? again = 1; /* no callback will be called! */ } } @@ -356,8 +353,8 @@ static void gigaset_modem_fill(unsigned long data) */ static void gigaset_read_int_callback(struct urb *urb) { - struct inbuf_t *inbuf = urb->context; - struct cardstate *cs = inbuf->cs; + struct cardstate *cs = urb->context; + struct inbuf_t *inbuf = cs->inbuf; int status = urb->status; int r; unsigned numbytes; @@ -368,7 +365,7 @@ static void gigaset_read_int_callback(struct urb *urb) numbytes = urb->actual_length; if (numbytes) { - src = inbuf->rcvbuf; + src = cs->hw.usb->rcvbuf; if (unlikely(*src)) dev_warn(cs->dev, "%s: There was no leading 0, but 0x%02x!\n", @@ -440,7 +437,7 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) struct cmdbuf_t *tcb; unsigned long flags; int count; - int status = -ENOENT; // FIXME + int status = -ENOENT; struct usb_cardstate *ucs = cs->hw.usb; do { @@ -480,7 +477,9 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) ucs->busy = 1; spin_lock_irqsave(&cs->lock, flags); - status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : -ENODEV; + status = cs->connected ? + usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : + -ENODEV; spin_unlock_irqrestore(&cs->lock, flags); if (status) { @@ -510,8 +509,8 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, if (len <= 0) return 0; - - if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { + cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC); + if (!cb) { dev_err(cs->dev, "%s: out of memory\n", __func__); return -ENOMEM; } @@ -637,9 +636,7 @@ static int write_modem(struct cardstate *cs) return -EINVAL; } - /* Copy data to bulk out buffer and // FIXME copying not necessary - * transmit data - */ + /* Copy data to bulk out buffer and transmit data */ count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size); skb_copy_from_linear_data(bcs->tx_skb, ucs->bulk_out_buffer, count); skb_pull(bcs->tx_skb, count); @@ -650,7 +647,8 @@ static int write_modem(struct cardstate *cs) if (cs->connected) { usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, usb_sndbulkpipe(ucs->udev, - ucs->bulk_out_endpointAddr & 0x0f), + ucs->bulk_out_endpointAddr & + 0x0f), ucs->bulk_out_buffer, count, gigaset_write_bulk_callback, cs); ret = usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC); @@ -666,7 +664,7 @@ static int write_modem(struct cardstate *cs) if (!bcs->tx_skb->len) { /* skb sent completely */ - gigaset_skb_sent(bcs, bcs->tx_skb); //FIXME also, when ret<0? + gigaset_skb_sent(bcs, bcs->tx_skb); gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!", (unsigned long) bcs->tx_skb); @@ -763,8 +761,8 @@ static int gigaset_probe(struct usb_interface *interface, buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); ucs->rcvbuf_size = buffer_size; ucs->int_in_endpointAddr = endpoint->bEndpointAddress; - cs->inbuf[0].rcvbuf = kmalloc(buffer_size, GFP_KERNEL); - if (!cs->inbuf[0].rcvbuf) { + ucs->rcvbuf = kmalloc(buffer_size, GFP_KERNEL); + if (!ucs->rcvbuf) { dev_err(cs->dev, "Couldn't allocate rcvbuf\n"); retval = -ENOMEM; goto error; @@ -773,9 +771,9 @@ static int gigaset_probe(struct usb_interface *interface, usb_fill_int_urb(ucs->read_urb, udev, usb_rcvintpipe(udev, endpoint->bEndpointAddress & 0x0f), - cs->inbuf[0].rcvbuf, buffer_size, + ucs->rcvbuf, buffer_size, gigaset_read_int_callback, - cs->inbuf + 0, endpoint->bInterval); + cs, endpoint->bInterval); retval = usb_submit_urb(ucs->read_urb, GFP_KERNEL); if (retval) { @@ -789,7 +787,7 @@ static int gigaset_probe(struct usb_interface *interface, if (!gigaset_start(cs)) { tasklet_kill(&cs->write_tasklet); - retval = -ENODEV; //FIXME + retval = -ENODEV; goto error; } return 0; @@ -798,11 +796,11 @@ error: usb_kill_urb(ucs->read_urb); kfree(ucs->bulk_out_buffer); usb_free_urb(ucs->bulk_out_urb); - kfree(cs->inbuf[0].rcvbuf); + kfree(ucs->rcvbuf); usb_free_urb(ucs->read_urb); usb_set_intfdata(interface, NULL); ucs->read_urb = ucs->bulk_out_urb = NULL; - cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL; + ucs->rcvbuf = ucs->bulk_out_buffer = NULL; usb_put_dev(ucs->udev); ucs->udev = NULL; ucs->interface = NULL; @@ -831,10 +829,10 @@ static void gigaset_disconnect(struct usb_interface *interface) kfree(ucs->bulk_out_buffer); usb_free_urb(ucs->bulk_out_urb); - kfree(cs->inbuf[0].rcvbuf); + kfree(ucs->rcvbuf); usb_free_urb(ucs->read_urb); ucs->read_urb = ucs->bulk_out_urb = NULL; - cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL; + ucs->rcvbuf = ucs->bulk_out_buffer = NULL; usb_put_dev(ucs->udev); ucs->interface = NULL; @@ -916,9 +914,10 @@ static int __init usb_gigaset_init(void) int result; /* allocate memory for our driver state and intialize it */ - if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, - GIGASET_MODULENAME, GIGASET_DEVNAME, - &ops, THIS_MODULE)) == NULL) + driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, + GIGASET_MODULENAME, GIGASET_DEVNAME, + &ops, THIS_MODULE); + if (driver == NULL) goto error; /* register this driver with the USB subsystem */ -- cgit v1.2.2 From d9ba9c9125d89e246dc0a0702446528acceb6ddb Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sun, 25 Oct 2009 09:30:17 +0000 Subject: gigaset: checkpatch cleanup Dum sanctis checkpatch.pl'ae legibus obsequimur. Impact: cosmetic Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/common.c | 33 ++++++++++------------ drivers/isdn/gigaset/gigaset.h | 60 +++++++++++++++++++--------------------- drivers/isdn/gigaset/i4l.c | 29 ++++++++----------- drivers/isdn/gigaset/interface.c | 39 ++++++++++++-------------- drivers/isdn/gigaset/proc.c | 2 +- 5 files changed, 74 insertions(+), 89 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 690ac74c82a8..c438cfcb7c6d 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -108,7 +108,7 @@ int gigaset_enterconfigmode(struct cardstate *cs) { int i, r; - cs->control_state = TIOCM_RTS; //FIXME + cs->control_state = TIOCM_RTS; r = setflags(cs, TIOCM_DTR, 200); if (r < 0) @@ -132,10 +132,10 @@ int gigaset_enterconfigmode(struct cardstate *cs) error: dev_err(cs->dev, "error %d on setuartbits\n", -r); - cs->control_state = TIOCM_RTS|TIOCM_DTR; // FIXME is this a good value? + cs->control_state = TIOCM_RTS|TIOCM_DTR; cs->ops->set_modem_ctrl(cs, 0, TIOCM_RTS|TIOCM_DTR); - return -1; //r + return -1; } static int test_timeout(struct at_state_t *at_state) @@ -150,10 +150,9 @@ static int test_timeout(struct at_state_t *at_state) } if (!gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL, - at_state->timer_index, NULL)) { - //FIXME what should we do? - } - + at_state->timer_index, NULL)) + dev_err(at_state->cs->dev, "%s: out of memory\n", + __func__); return 1; } @@ -393,9 +392,8 @@ static void gigaset_freebcs(struct bc_state *bcs) int i; gig_dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel); - if (!bcs->cs->ops->freebcshw(bcs)) { + if (!bcs->cs->ops->freebcshw(bcs)) gig_dbg(DEBUG_INIT, "failed"); - } gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel); clear_at_state(&bcs->at_state); @@ -503,8 +501,6 @@ void gigaset_freecs(struct cardstate *cs) gig_dbg(DEBUG_INIT, "clearing hw"); cs->ops->freecshw(cs); - //FIXME cmdbuf - /* fall through */ case 2: /* error in initcshw */ /* Deregister from LL */ @@ -622,7 +618,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, { int i; - bcs->tx_skb = NULL; //FIXME -> hw part + bcs->tx_skb = NULL; skb_queue_head_init(&bcs->squeue); @@ -696,12 +692,13 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, int onechannel, int ignoreframes, int cidmode, const char *modulename) { - struct cardstate *cs = NULL; + struct cardstate *cs; unsigned long flags; int i; gig_dbg(DEBUG_INIT, "allocating cs"); - if (!(cs = alloc_cs(drv))) { + cs = alloc_cs(drv); + if (!cs) { pr_err("maximum number of devices exceeded\n"); return NULL; } @@ -931,15 +928,13 @@ int gigaset_start(struct cardstate *cs) cs->ops->baud_rate(cs, B115200); cs->ops->set_line_ctrl(cs, CS8); cs->control_state = TIOCM_DTR|TIOCM_RTS; - } else { - //FIXME use some saved values? } cs->waiting = 1; if (!gigaset_add_event(cs, &cs->at_state, EV_START, NULL, 0, NULL)) { cs->waiting = 0; - //FIXME what should we do? + dev_err(cs->dev, "%s: out of memory\n", __func__); goto error; } @@ -979,7 +974,7 @@ int gigaset_shutdown(struct cardstate *cs) cs->waiting = 1; if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) { - //FIXME what should we do? + dev_err(cs->dev, "%s: out of memory\n", __func__); goto exit; } @@ -1010,7 +1005,7 @@ void gigaset_stop(struct cardstate *cs) cs->waiting = 1; if (!gigaset_add_event(cs, &cs->at_state, EV_STOP, NULL, 0, NULL)) { - //FIXME what should we do? + dev_err(cs->dev, "%s: out of memory\n", __func__); goto exit; } diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 18bff9f80727..3c74cd164019 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -34,8 +34,8 @@ #include #include -#define GIG_VERSION {0,5,0,0} -#define GIG_COMPAT {0,4,0,0} +#define GIG_VERSION {0, 5, 0, 0} +#define GIG_COMPAT {0, 4, 0, 0} #define MAX_REC_PARAMS 10 /* Max. number of params in response string */ #define MAX_RESP_SIZE 512 /* Max. size of a response string */ @@ -133,35 +133,32 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, #define OUT_VENDOR_REQ (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) #define IN_VENDOR_REQ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) -/* int-in-events 3070 */ +/* interrupt pipe messages */ #define HD_B1_FLOW_CONTROL 0x80 #define HD_B2_FLOW_CONTROL 0x81 -#define HD_RECEIVEATDATA_ACK (0x35) // 3070 - // att: HD_RECEIVE>>AT<: "X" "." @@ -776,7 +774,7 @@ struct event_t *gigaset_add_event(struct cardstate *cs, void *ptr, int parameter, void *arg); /* Called on CONFIG1 command from frontend. */ -int gigaset_enterconfigmode(struct cardstate *cs); //0: success <0: errorcode +int gigaset_enterconfigmode(struct cardstate *cs); /* cs->lock must not be locked */ static inline void gigaset_schedule_event(struct cardstate *cs) diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c index 828824f905c4..c129ee47a8fb 100644 --- a/drivers/isdn/gigaset/i4l.c +++ b/drivers/isdn/gigaset/i4l.c @@ -39,12 +39,12 @@ static int writebuf_from_LL(int driverID, int channel, int ack, struct sk_buff *skb) { - struct cardstate *cs; + struct cardstate *cs = gigaset_get_cs_by_id(driverID); struct bc_state *bcs; unsigned char *ack_header; unsigned len; - if (!(cs = gigaset_get_cs_by_id(driverID))) { + if (!cs) { pr_err("%s: invalid driver ID (%d)\n", __func__, driverID); return -ENODEV; } @@ -391,22 +391,19 @@ static int command_from_LL(isdn_ctrl *cntrl) break; case ISDN_CMD_PROCEED: - gig_dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); //FIXME + gig_dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); break; case ISDN_CMD_ALERT: - gig_dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); //FIXME + gig_dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); if (cntrl->arg >= cs->channels) { dev_err(cs->dev, "ISDN_CMD_ALERT: invalid channel (%d)\n", (int) cntrl->arg); return -EINVAL; } - //bcs = cs->bcs + cntrl->arg; - //bcs->proto2 = -1; - // FIXME break; case ISDN_CMD_REDIR: - gig_dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); //FIXME + gig_dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); break; case ISDN_CMD_PROT_IO: gig_dbg(DEBUG_ANY, "ISDN_CMD_PROT_IO"); @@ -486,7 +483,7 @@ int gigaset_isdn_icall(struct at_state_t *at_state) /* fill ICALL structure */ response.parm.setup.si1 = 0; /* default: unknown */ response.parm.setup.si2 = 0; - response.parm.setup.screen = 0; //FIXME how to set these? + response.parm.setup.screen = 0; response.parm.setup.plan = 0; if (!at_state->str_var[STR_ZBC]) { /* no BC (internal call): assume speech, A-law */ @@ -507,26 +504,24 @@ int gigaset_isdn_icall(struct at_state_t *at_state) return ICALL_IGNORE; } if (at_state->str_var[STR_NMBR]) { - strncpy(response.parm.setup.phone, at_state->str_var[STR_NMBR], - sizeof response.parm.setup.phone - 1); - response.parm.setup.phone[sizeof response.parm.setup.phone - 1] = 0; + strlcpy(response.parm.setup.phone, at_state->str_var[STR_NMBR], + sizeof response.parm.setup.phone); } else response.parm.setup.phone[0] = 0; if (at_state->str_var[STR_ZCPN]) { - strncpy(response.parm.setup.eazmsn, at_state->str_var[STR_ZCPN], - sizeof response.parm.setup.eazmsn - 1); - response.parm.setup.eazmsn[sizeof response.parm.setup.eazmsn - 1] = 0; + strlcpy(response.parm.setup.eazmsn, at_state->str_var[STR_ZCPN], + sizeof response.parm.setup.eazmsn); } else response.parm.setup.eazmsn[0] = 0; if (!bcs) { dev_notice(cs->dev, "no channel for incoming call\n"); response.command = ISDN_STAT_ICALLW; - response.arg = 0; //FIXME + response.arg = 0; } else { gig_dbg(DEBUG_CMD, "Sending ICALL"); response.command = ISDN_STAT_ICALL; - response.arg = bcs->channel; //FIXME + response.arg = bcs->channel; } response.driver = cs->myid; retval = iif->statcallb(&response); diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index 6a8e1384e7bd..577809c03aed 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -162,7 +162,7 @@ static int if_open(struct tty_struct *tty, struct file *filp) return -ENODEV; if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; // FIXME -EINTR? + return -ERESTARTSYS; tty->driver_data = cs; ++cs->open_count; @@ -171,7 +171,7 @@ static int if_open(struct tty_struct *tty, struct file *filp) spin_lock_irqsave(&cs->lock, flags); cs->tty = tty; spin_unlock_irqrestore(&cs->lock, flags); - tty->low_latency = 1; //FIXME test + tty->low_latency = 1; } mutex_unlock(&cs->mutex); @@ -228,7 +228,7 @@ static int if_ioctl(struct tty_struct *tty, struct file *file, gig_dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __func__, cmd); if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; // FIXME -EINTR? + return -ERESTARTSYS; if (!cs->connected) { gig_dbg(DEBUG_IF, "not connected"); @@ -299,9 +299,8 @@ static int if_tiocmget(struct tty_struct *tty, struct file *file) gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; // FIXME -EINTR? + return -ERESTARTSYS; - // FIXME read from device? retval = cs->control_state & (TIOCM_RTS|TIOCM_DTR); mutex_unlock(&cs->mutex); @@ -326,7 +325,7 @@ static int if_tiocmset(struct tty_struct *tty, struct file *file, cs->minor_index, __func__, set, clear); if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; // FIXME -EINTR? + return -ERESTARTSYS; if (!cs->connected) { gig_dbg(DEBUG_IF, "not connected"); @@ -356,7 +355,7 @@ static int if_write(struct tty_struct *tty, const unsigned char *buf, int count) gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; // FIXME -EINTR? + return -ERESTARTSYS; if (!cs->connected) { gig_dbg(DEBUG_IF, "not connected"); @@ -390,7 +389,7 @@ static int if_write_room(struct tty_struct *tty) gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; // FIXME -EINTR? + return -ERESTARTSYS; if (!cs->connected) { gig_dbg(DEBUG_IF, "not connected"); @@ -455,9 +454,8 @@ static void if_throttle(struct tty_struct *tty) gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ else if (!cs->open_count) dev_warn(cs->dev, "%s: device not opened\n", __func__); - else { - //FIXME - } + else + gig_dbg(DEBUG_ANY, "%s: not implemented\n", __func__); mutex_unlock(&cs->mutex); } @@ -480,9 +478,8 @@ static void if_unthrottle(struct tty_struct *tty) gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ else if (!cs->open_count) dev_warn(cs->dev, "%s: device not opened\n", __func__); - else { - //FIXME - } + else + gig_dbg(DEBUG_ANY, "%s: not implemented\n", __func__); mutex_unlock(&cs->mutex); } @@ -515,10 +512,9 @@ static void if_set_termios(struct tty_struct *tty, struct ktermios *old) goto out; } - // stolen from mct_u232.c iflag = tty->termios->c_iflag; cflag = tty->termios->c_cflag; - old_cflag = old ? old->c_cflag : cflag; //FIXME? + old_cflag = old ? old->c_cflag : cflag; gig_dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x", cs->minor_index, iflag, cflag, old_cflag); @@ -632,7 +628,8 @@ void gigaset_if_receive(struct cardstate *cs, struct tty_struct *tty; spin_lock_irqsave(&cs->lock, flags); - if ((tty = cs->tty) == NULL) + tty = cs->tty; + if (tty == NULL) gig_dbg(DEBUG_ANY, "receive on closed device"); else { tty_buffer_request_room(tty, len); @@ -659,9 +656,9 @@ void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, drv->have_tty = 0; - if ((drv->tty = alloc_tty_driver(minors)) == NULL) + drv->tty = tty = alloc_tty_driver(minors); + if (tty == NULL) goto enomem; - tty = drv->tty; tty->magic = TTY_DRIVER_MAGIC, tty->major = GIG_MAJOR, @@ -676,8 +673,8 @@ void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, tty->owner = THIS_MODULE; - tty->init_termios = tty_std_termios; //FIXME - tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; //FIXME + tty->init_termios = tty_std_termios; + tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; tty_set_operations(tty, &if_ops); ret = tty_register_driver(tty); diff --git a/drivers/isdn/gigaset/proc.c b/drivers/isdn/gigaset/proc.c index 9715aad9c3f0..758a00c1d2e2 100644 --- a/drivers/isdn/gigaset/proc.c +++ b/drivers/isdn/gigaset/proc.c @@ -39,7 +39,7 @@ static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, return -EINVAL; if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; // FIXME -EINTR? + return -ERESTARTSYS; cs->waiting = 1; if (!gigaset_add_event(cs, &cs->at_state, EV_PROC_CIDMODE, -- cgit v1.2.2 From ae67d7d81436c7e85104d586562b1a220d3cd94b Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sun, 25 Oct 2009 09:30:27 +0000 Subject: ser_gigaset: checkpatch cleanup Duly uglified as demanded by checkpatch.pl. Impact: cosmetic Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/ser-gigaset.c | 56 +++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 19 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index 3071a52467ed..ac3409ea5d99 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c @@ -164,9 +164,15 @@ static void gigaset_modem_fill(unsigned long data) { struct cardstate *cs = (struct cardstate *) data; struct bc_state *bcs; + struct sk_buff *nextskb; int sent = 0; - if (!cs || !(bcs = cs->bcs)) { + if (!cs) { + gig_dbg(DEBUG_OUTPUT, "%s: no cardstate", __func__); + return; + } + bcs = cs->bcs; + if (!bcs) { gig_dbg(DEBUG_OUTPUT, "%s: no cardstate", __func__); return; } @@ -179,9 +185,11 @@ static void gigaset_modem_fill(unsigned long data) return; /* no command to send; get skb */ - if (!(bcs->tx_skb = skb_dequeue(&bcs->squeue))) + nextskb = skb_dequeue(&bcs->squeue); + if (!nextskb) /* no skb either, nothing to do */ return; + bcs->tx_skb = nextskb; gig_dbg(DEBUG_INTR, "Dequeued skb (Adr: %lx)", (unsigned long) bcs->tx_skb); @@ -236,19 +244,20 @@ static void flush_send_queue(struct cardstate *cs) * number of bytes queued, or error code < 0 */ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, - int len, struct tasklet_struct *wake_tasklet) + int len, struct tasklet_struct *wake_tasklet) { struct cmdbuf_t *cb; unsigned long flags; gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? - DEBUG_TRANSCMD : DEBUG_LOCKCMD, - "CMD Transmit", len, buf); + DEBUG_TRANSCMD : DEBUG_LOCKCMD, + "CMD Transmit", len, buf); if (len <= 0) return 0; - if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { + cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC); + if (!cb) { dev_err(cs->dev, "%s: out of memory!\n", __func__); return -ENOMEM; } @@ -392,7 +401,6 @@ static void gigaset_device_release(struct device *dev) struct platform_device *pdev = to_platform_device(dev); /* adapted from platform_device_release() in drivers/base/platform.c */ - //FIXME is this actually necessary? kfree(dev->platform_data); kfree(pdev->resource); } @@ -404,16 +412,20 @@ static void gigaset_device_release(struct device *dev) static int gigaset_initcshw(struct cardstate *cs) { int rc; + struct ser_cardstate *scs; - if (!(cs->hw.ser = kzalloc(sizeof(struct ser_cardstate), GFP_KERNEL))) { + scs = kzalloc(sizeof(struct ser_cardstate), GFP_KERNEL); + if (!scs) { pr_err("out of memory\n"); return 0; } + cs->hw.ser = scs; cs->hw.ser->dev.name = GIGASET_MODULENAME; cs->hw.ser->dev.id = cs->minor_index; cs->hw.ser->dev.dev.release = gigaset_device_release; - if ((rc = platform_device_register(&cs->hw.ser->dev)) != 0) { + rc = platform_device_register(&cs->hw.ser->dev); + if (rc != 0) { pr_err("error %d registering platform device\n", rc); kfree(cs->hw.ser); cs->hw.ser = NULL; @@ -422,7 +434,7 @@ static int gigaset_initcshw(struct cardstate *cs) dev_set_drvdata(&cs->hw.ser->dev.dev, cs); tasklet_init(&cs->write_tasklet, - &gigaset_modem_fill, (unsigned long) cs); + &gigaset_modem_fill, (unsigned long) cs); return 1; } @@ -434,7 +446,8 @@ static int gigaset_initcshw(struct cardstate *cs) * Called by "gigaset_start" and "gigaset_enterconfigmode" in common.c * and by "if_lock" and "if_termios" in interface.c */ -static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, unsigned new_state) +static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, + unsigned new_state) { struct tty_struct *tty = cs->hw.ser->tty; unsigned int set, clear; @@ -520,8 +533,8 @@ gigaset_tty_open(struct tty_struct *tty) } /* allocate memory for our device state and intialize it */ - if (!(cs = gigaset_initcs(driver, 1, 1, 0, cidmode, - GIGASET_MODULENAME))) + cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); + if (!cs) goto error; cs->dev = &cs->hw.ser->dev.dev; @@ -690,7 +703,8 @@ gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf, if (!cs) return; - if (!(inbuf = cs->inbuf)) { + inbuf = cs->inbuf; + if (!inbuf) { dev_err(cs->dev, "%s: no inbuf\n", __func__); cs_put(cs); return; @@ -770,18 +784,21 @@ static int __init ser_gigaset_init(void) int rc; gig_dbg(DEBUG_INIT, "%s", __func__); - if ((rc = platform_driver_register(&device_driver)) != 0) { + rc = platform_driver_register(&device_driver); + if (rc != 0) { pr_err("error %d registering platform driver\n", rc); return rc; } /* allocate memory for our driver state and intialize it */ - if (!(driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, + driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, GIGASET_MODULENAME, GIGASET_DEVNAME, - &ops, THIS_MODULE))) + &ops, THIS_MODULE); + if (!driver) goto error; - if ((rc = tty_register_ldisc(N_GIGASET_M101, &gigaset_ldisc)) != 0) { + rc = tty_register_ldisc(N_GIGASET_M101, &gigaset_ldisc); + if (rc != 0) { pr_err("error %d registering line discipline\n", rc); goto error; } @@ -808,7 +825,8 @@ static void __exit ser_gigaset_exit(void) driver = NULL; } - if ((rc = tty_unregister_ldisc(N_GIGASET_M101)) != 0) + rc = tty_unregister_ldisc(N_GIGASET_M101); + if (rc != 0) pr_err("error %d unregistering line discipline\n", rc); platform_driver_unregister(&device_driver); -- cgit v1.2.2 From 7891adf18ad9658950e532b840f1d84d8ac6cce2 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sun, 25 Oct 2009 09:30:37 +0000 Subject: bas_gigaset: checkpatch cleanup On the quest for the holy grail of checkpatch.pl silence. Impact: cosmetic Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/bas-gigaset.c | 68 +++++++++++++---------- drivers/isdn/gigaset/isocdata.c | 107 ++++++++++++++++++------------------- 2 files changed, 93 insertions(+), 82 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 388e63a8ae94..9fd19db045fb 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -57,7 +57,7 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode"); #define USB_SX353_PRODUCT_ID 0x0022 /* table of devices that work with this driver */ -static const struct usb_device_id gigaset_table [] = { +static const struct usb_device_id gigaset_table[] = { { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3070_PRODUCT_ID) }, { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3075_PRODUCT_ID) }, { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX303_PRODUCT_ID) }, @@ -137,7 +137,7 @@ struct bas_cardstate { #define BS_RESETTING 0x200 /* waiting for HD_RESET_INTERRUPT_PIPE_ACK */ -static struct gigaset_driver *driver = NULL; +static struct gigaset_driver *driver; /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver gigaset_usb_driver = { @@ -601,11 +601,12 @@ static int atread_submit(struct cardstate *cs, int timeout) ucs->dr_cmd_in.wLength = cpu_to_le16(ucs->rcvbuf_size); usb_fill_control_urb(ucs->urb_cmd_in, ucs->udev, usb_rcvctrlpipe(ucs->udev, 0), - (unsigned char*) & ucs->dr_cmd_in, + (unsigned char *) &ucs->dr_cmd_in, ucs->rcvbuf, ucs->rcvbuf_size, read_ctrl_callback, cs->inbuf); - if ((ret = usb_submit_urb(ucs->urb_cmd_in, GFP_ATOMIC)) != 0) { + ret = usb_submit_urb(ucs->urb_cmd_in, GFP_ATOMIC); + if (ret != 0) { update_basstate(ucs, 0, BS_ATRDPEND); dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n", get_usb_rcmsg(ret)); @@ -652,13 +653,11 @@ static void read_int_callback(struct urb *urb) return; case -ENODEV: /* device removed */ case -ESHUTDOWN: /* device shut down */ - //FIXME use this as disconnect indicator? gig_dbg(DEBUG_USBREQ, "%s: device disconnected", __func__); return; default: /* severe trouble */ dev_warn(cs->dev, "interrupt read: %s\n", get_usb_statmsg(status)); - //FIXME corrective action? resubmission always ok? goto resubmit; } @@ -742,7 +741,8 @@ static void read_int_callback(struct urb *urb) kfree(ucs->rcvbuf); ucs->rcvbuf_size = 0; } - if ((ucs->rcvbuf = kmalloc(l, GFP_ATOMIC)) == NULL) { + ucs->rcvbuf = kmalloc(l, GFP_ATOMIC); + if (ucs->rcvbuf == NULL) { spin_unlock_irqrestore(&cs->lock, flags); dev_err(cs->dev, "out of memory receiving AT data\n"); error_reset(cs); @@ -750,12 +750,12 @@ static void read_int_callback(struct urb *urb) } ucs->rcvbuf_size = l; ucs->retry_cmd_in = 0; - if ((rc = atread_submit(cs, BAS_TIMEOUT)) < 0) { + rc = atread_submit(cs, BAS_TIMEOUT); + if (rc < 0) { kfree(ucs->rcvbuf); ucs->rcvbuf = NULL; ucs->rcvbuf_size = 0; if (rc != -ENODEV) { - //FIXME corrective action? spin_unlock_irqrestore(&cs->lock, flags); error_reset(cs); break; @@ -940,7 +940,8 @@ static int starturbs(struct bc_state *bcs) } dump_urb(DEBUG_ISO, "Initial isoc read", urb); - if ((rc = usb_submit_urb(urb, GFP_ATOMIC)) != 0) + rc = usb_submit_urb(urb, GFP_ATOMIC); + if (rc != 0) goto error; } @@ -1045,7 +1046,8 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) /* compute frame length according to flow control */ ifd->length = BAS_NORMFRAME; - if ((corrbytes = atomic_read(&ubc->corrbytes)) != 0) { + corrbytes = atomic_read(&ubc->corrbytes); + if (corrbytes != 0) { gig_dbg(DEBUG_ISO, "%s: corrbytes=%d", __func__, corrbytes); if (corrbytes > BAS_HIGHFRAME - BAS_NORMFRAME) @@ -1284,7 +1286,8 @@ static void read_iso_tasklet(unsigned long data) for (;;) { /* retrieve URB */ spin_lock_irqsave(&ubc->isoinlock, flags); - if (!(urb = ubc->isoindone)) { + urb = ubc->isoindone; + if (!urb) { spin_unlock_irqrestore(&ubc->isoinlock, flags); return; } @@ -1371,7 +1374,7 @@ static void read_iso_tasklet(unsigned long data) "isochronous read: %d data bytes missing\n", totleft); - error: +error: /* URB processed, resubmit */ for (frame = 0; frame < BAS_NUMFRAMES; frame++) { urb->iso_frame_desc[frame].status = 0; @@ -1568,7 +1571,7 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout) ucs->dr_ctrl.wLength = 0; usb_fill_control_urb(ucs->urb_ctrl, ucs->udev, usb_sndctrlpipe(ucs->udev, 0), - (unsigned char*) &ucs->dr_ctrl, NULL, 0, + (unsigned char *) &ucs->dr_ctrl, NULL, 0, write_ctrl_callback, ucs); ucs->retry_ctrl = 0; ret = usb_submit_urb(ucs->urb_ctrl, GFP_ATOMIC); @@ -1621,7 +1624,8 @@ static int gigaset_init_bchannel(struct bc_state *bcs) return -EHOSTUNREACH; } - if ((ret = starturbs(bcs)) < 0) { + ret = starturbs(bcs); + if (ret < 0) { dev_err(cs->dev, "could not start isochronous I/O for channel B%d: %s\n", bcs->channel + 1, @@ -1633,7 +1637,8 @@ static int gigaset_init_bchannel(struct bc_state *bcs) } req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL; - if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) { + ret = req_submit(bcs, req, 0, BAS_TIMEOUT); + if (ret < 0) { dev_err(cs->dev, "could not open channel B%d\n", bcs->channel + 1); stopurbs(bcs->hw.bas); @@ -1677,7 +1682,8 @@ static int gigaset_close_bchannel(struct bc_state *bcs) /* channel running: tell device to close it */ req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL; - if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) + ret = req_submit(bcs, req, 0, BAS_TIMEOUT); + if (ret < 0) dev_err(cs->dev, "closing channel B%d failed\n", bcs->channel + 1); @@ -1703,10 +1709,12 @@ static void complete_cb(struct cardstate *cs) gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "write_command: sent %u bytes, %u left", cs->curlen, cs->cmdbytes); - if ((cs->cmdbuf = cb->next) != NULL) { + if (cb->next != NULL) { + cs->cmdbuf = cb->next; cs->cmdbuf->prev = NULL; cs->curlen = cs->cmdbuf->len; } else { + cs->cmdbuf = NULL; cs->lastcmdbuf = NULL; cs->curlen = 0; } @@ -1833,7 +1841,7 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len) ucs->dr_cmd_out.wLength = cpu_to_le16(len); usb_fill_control_urb(ucs->urb_cmd_out, ucs->udev, usb_sndctrlpipe(ucs->udev, 0), - (unsigned char*) &ucs->dr_cmd_out, buf, len, + (unsigned char *) &ucs->dr_cmd_out, buf, len, write_command_callback, cs); rc = usb_submit_urb(ucs->urb_cmd_out, GFP_ATOMIC); if (unlikely(rc)) { @@ -1953,7 +1961,8 @@ static int gigaset_write_cmd(struct cardstate *cs, if (len > IF_WRITEBUF) len = IF_WRITEBUF; - if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { + cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC); + if (!cb) { dev_err(cs->dev, "%s: out of memory\n", __func__); rc = -ENOMEM; goto notqueued; @@ -2100,7 +2109,8 @@ static int gigaset_initbcshw(struct bc_state *bcs) } ubc->isooutdone = ubc->isooutfree = ubc->isooutovfl = NULL; ubc->numsub = 0; - if (!(ubc->isooutbuf = kmalloc(sizeof(struct isowbuf_t), GFP_KERNEL))) { + ubc->isooutbuf = kmalloc(sizeof(struct isowbuf_t), GFP_KERNEL); + if (!ubc->isooutbuf) { pr_err("out of memory\n"); kfree(ubc); bcs->hw.bas = NULL; @@ -2252,7 +2262,8 @@ static int gigaset_probe(struct usb_interface *interface, gig_dbg(DEBUG_ANY, "%s: wrong alternate setting %d - trying to switch", __func__, hostif->desc.bAlternateSetting); - if (usb_set_interface(udev, hostif->desc.bInterfaceNumber, 3) < 0) { + if (usb_set_interface(udev, hostif->desc.bInterfaceNumber, 3) + < 0) { dev_warn(&udev->dev, "usb_set_interface failed, " "device %d interface %d altsetting %d\n", udev->devnum, hostif->desc.bInterfaceNumber, @@ -2321,14 +2332,16 @@ static int gigaset_probe(struct usb_interface *interface, (endpoint->bEndpointAddress) & 0x0f), ucs->int_in_buf, IP_MSGSIZE, read_int_callback, cs, endpoint->bInterval); - if ((rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL)) != 0) { + rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL); + if (rc != 0) { dev_err(cs->dev, "could not submit interrupt URB: %s\n", get_usb_rcmsg(rc)); goto error; } /* tell the device that the driver is ready */ - if ((rc = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0)) != 0) + rc = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0); + if (rc != 0) goto error; /* tell common part that the device is ready */ @@ -2524,9 +2537,10 @@ static int __init bas_gigaset_init(void) int result; /* allocate memory for our driver state and intialize it */ - if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, - GIGASET_MODULENAME, GIGASET_DEVNAME, - &gigops, THIS_MODULE)) == NULL) + driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, + GIGASET_MODULENAME, GIGASET_DEVNAME, + &gigops, THIS_MODULE); + if (driver == NULL) goto error; /* register this driver with the USB subsystem */ diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index bc41611e541d..85394a6ebae8 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c @@ -41,7 +41,8 @@ static inline int isowbuf_freebytes(struct isowbuf_t *iwb) read = iwb->read; write = iwb->write; - if ((freebytes = read - write) > 0) { + freebytes = read - write; + if (freebytes > 0) { /* no wraparound: need padding space within regular area */ return freebytes - BAS_OUTBUFPAD; } else if (read < BAS_OUTBUFPAD) { @@ -53,29 +54,6 @@ static inline int isowbuf_freebytes(struct isowbuf_t *iwb) } } -/* compare two offsets within the buffer - * The buffer is seen as circular, with the read position as start - * returns -1/0/1 if position a position b without crossing 'read' - */ -static inline int isowbuf_poscmp(struct isowbuf_t *iwb, int a, int b) -{ - int read; - if (a == b) - return 0; - read = iwb->read; - if (a < b) { - if (a < read && read <= b) - return +1; - else - return -1; - } else { - if (b < read && read <= a) - return -1; - else - return +1; - } -} - /* start writing * acquire the write semaphore * return true if acquired, false if busy @@ -271,7 +249,7 @@ static inline void dump_bytes(enum debuglevel level, const char *tag, * bit 14..13 = number of bits added by stuffing */ static const u16 stufftab[5 * 256] = { -// previous 1s = 0: +/* previous 1s = 0: */ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x201f, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, @@ -289,7 +267,7 @@ static const u16 stufftab[5 * 256] = { 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x0cef, 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x2ddf, -// previous 1s = 1: +/* previous 1s = 1: */ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x200f, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x202f, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x204f, @@ -307,7 +285,7 @@ static const u16 stufftab[5 * 256] = { 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dcf, 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x31ef, -// previous 1s = 2: +/* previous 1s = 2: */ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x2007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x2017, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x2027, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x2037, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x2047, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x2057, @@ -325,7 +303,7 @@ static const u16 stufftab[5 * 256] = { 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dc7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dd7, 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x31e7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x41f7, -// previous 1s = 3: +/* previous 1s = 3: */ 0x0000, 0x0001, 0x0002, 0x2003, 0x0004, 0x0005, 0x0006, 0x200b, 0x0008, 0x0009, 0x000a, 0x2013, 0x000c, 0x000d, 0x000e, 0x201b, 0x0010, 0x0011, 0x0012, 0x2023, 0x0014, 0x0015, 0x0016, 0x202b, 0x0018, 0x0019, 0x001a, 0x2033, 0x001c, 0x001d, 0x001e, 0x203b, 0x0020, 0x0021, 0x0022, 0x2043, 0x0024, 0x0025, 0x0026, 0x204b, 0x0028, 0x0029, 0x002a, 0x2053, 0x002c, 0x002d, 0x002e, 0x205b, @@ -343,7 +321,7 @@ static const u16 stufftab[5 * 256] = { 0x0ce0, 0x0ce1, 0x0ce2, 0x2dc3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dcb, 0x0ce8, 0x0ce9, 0x0cea, 0x2dd3, 0x0cec, 0x0ced, 0x0cee, 0x2ddb, 0x10f0, 0x10f1, 0x10f2, 0x31e3, 0x10f4, 0x10f5, 0x10f6, 0x31eb, 0x20f8, 0x20f9, 0x20fa, 0x41f3, 0x257c, 0x257d, 0x29be, 0x46fb, -// previous 1s = 4: +/* previous 1s = 4: */ 0x0000, 0x2001, 0x0002, 0x2005, 0x0004, 0x2009, 0x0006, 0x200d, 0x0008, 0x2011, 0x000a, 0x2015, 0x000c, 0x2019, 0x000e, 0x201d, 0x0010, 0x2021, 0x0012, 0x2025, 0x0014, 0x2029, 0x0016, 0x202d, 0x0018, 0x2031, 0x001a, 0x2035, 0x001c, 0x2039, 0x001e, 0x203d, 0x0020, 0x2041, 0x0022, 0x2045, 0x0024, 0x2049, 0x0026, 0x204d, 0x0028, 0x2051, 0x002a, 0x2055, 0x002c, 0x2059, 0x002e, 0x205d, @@ -367,7 +345,8 @@ static const u16 stufftab[5 * 256] = { * parameters: * cin input byte * ones number of trailing '1' bits in result before this step - * iwb pointer to output buffer structure (write semaphore must be held) + * iwb pointer to output buffer structure + * (write semaphore must be held) * return value: * number of trailing '1' bits in result after this step */ @@ -408,7 +387,8 @@ static inline int hdlc_bitstuff_byte(struct isowbuf_t *iwb, unsigned char cin, * parameters: * in input buffer * count number of bytes in input buffer - * iwb pointer to output buffer structure (write semaphore must be held) + * iwb pointer to output buffer structure + * (write semaphore must be held) * return value: * position of end of packet in output buffer on success, * -EAGAIN if write semaphore busy or buffer full @@ -440,7 +420,8 @@ static inline int hdlc_buildframe(struct isowbuf_t *iwb, fcs = crc_ccitt_byte(fcs, c); } - /* bitstuff and append FCS (complemented, least significant byte first) */ + /* bitstuff and append FCS + * (complemented, least significant byte first) */ fcs ^= 0xffff; ones = hdlc_bitstuff_byte(iwb, fcs & 0x00ff, ones); ones = hdlc_bitstuff_byte(iwb, (fcs >> 8) & 0x00ff, ones); @@ -459,7 +440,8 @@ static inline int hdlc_buildframe(struct isowbuf_t *iwb, * parameters: * in input buffer * count number of bytes in input buffer - * iwb pointer to output buffer structure (write semaphore must be held) + * iwb pointer to output buffer structure + * (write semaphore must be held) * return value: * position of end of packet in output buffer on success, * -EAGAIN if write semaphore busy or buffer full @@ -567,8 +549,8 @@ static inline void hdlc_done(struct bc_state *bcs) hdlc_flush(bcs); return; } - - if ((procskb = bcs->skb) == NULL) { + procskb = bcs->skb; + if (procskb == NULL) { /* previous error */ gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__); gigaset_isdn_rcv_err(bcs); @@ -646,8 +628,8 @@ static const unsigned char bitcounts[256] = { }; /* hdlc_unpack - * perform HDLC frame processing (bit unstuffing, flag detection, FCS calculation) - * on a sequence of received data bytes (8 bits each, LSB first) + * perform HDLC frame processing (bit unstuffing, flag detection, FCS + * calculation) on a sequence of received data bytes (8 bits each, LSB first) * pass on successfully received, complete frames as SKBs via gigaset_skb_rcvd * notify of errors via gigaset_isdn_rcv_err * tally frames, errors etc. in BC structure counters @@ -665,9 +647,12 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, /* load previous state: * inputstate = set of flag bits: - * - INS_flag_hunt: no complete opening flag received since connection setup or last abort - * - INS_have_data: at least one complete data byte received since last flag - * seqlen = number of consecutive '1' bits in last 7 input stream bits (0..7) + * - INS_flag_hunt: no complete opening flag received since connection + * setup or last abort + * - INS_have_data: at least one complete data byte received since last + * flag + * seqlen = number of consecutive '1' bits in last 7 input stream bits + * (0..7) * inbyte = accumulated partial data byte (if !INS_flag_hunt) * inbits = number of valid bits in inbyte, starting at LSB (0..6) */ @@ -701,9 +686,11 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, inbyte = c >> (lead1 + 1); inbits = 7 - lead1; if (trail1 >= 8) { - /* interior stuffing: omitting the MSB handles most cases */ + /* interior stuffing: + * omitting the MSB handles most cases, + * correct the incorrectly handled + * cases individually */ inbits--; - /* correct the incorrectly handled cases individually */ switch (c) { case 0xbe: inbyte = 0x3f; @@ -729,13 +716,14 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, hdlc_flush(bcs); inputstate |= INS_flag_hunt; } else if (seqlen == 6) { - /* closing flag, including (6 - lead1) '1's and one '0' from inbits */ + /* closing flag, including (6 - lead1) '1's + * and one '0' from inbits */ if (inbits > 7 - lead1) { hdlc_frag(bcs, inbits + lead1 - 7); inputstate &= ~INS_have_data; } else { if (inbits < 7 - lead1) - ubc->stolen0s ++; + ubc->stolen0s++; if (inputstate & INS_have_data) { hdlc_done(bcs); inputstate &= ~INS_have_data; @@ -744,7 +732,7 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, if (c == PPP_FLAG) { /* complete flag, LSB overlaps preceding flag */ - ubc->shared0s ++; + ubc->shared0s++; inbits = 0; inbyte = 0; } else if (trail1 != 7) { @@ -752,9 +740,11 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, inbyte = c >> (lead1 + 1); inbits = 7 - lead1; if (trail1 >= 8) { - /* interior stuffing: omitting the MSB handles most cases */ + /* interior stuffing: + * omitting the MSB handles most cases, + * correct the incorrectly handled + * cases individually */ inbits--; - /* correct the incorrectly handled cases individually */ switch (c) { case 0xbe: inbyte = 0x3f; @@ -762,7 +752,8 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, } } } else { - /* abort sequence follows, skb already empty anyway */ + /* abort sequence follows, + * skb already empty anyway */ ubc->aborts++; inputstate |= INS_flag_hunt; } @@ -787,14 +778,17 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, } else { /* stuffed data */ if (trail1 < 7) { /* => seqlen == 5 */ - /* stuff bit at position lead1, no interior stuffing */ + /* stuff bit at position lead1, + * no interior stuffing */ unsigned char mask = (1 << lead1) - 1; c = (c & mask) | ((c & ~mask) >> 1); inbyte |= c << inbits; inbits += 7; } else if (seqlen < 5) { /* trail1 >= 8 */ - /* interior stuffing: omitting the MSB handles most cases */ - /* correct the incorrectly handled cases individually */ + /* interior stuffing: + * omitting the MSB handles most cases, + * correct the incorrectly handled + * cases individually */ switch (c) { case 0xbe: c = 0x7e; @@ -804,8 +798,9 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, inbits += 7; } else { /* seqlen == 5 && trail1 >= 8 */ - /* stuff bit at lead1 *and* interior stuffing */ - switch (c) { /* unstuff individually */ + /* stuff bit at lead1 *and* interior + * stuffing -- unstuff individually */ + switch (c) { case 0x7d: c = 0x3f; break; @@ -862,7 +857,8 @@ static inline void trans_receive(unsigned char *src, unsigned count, hdlc_flush(bcs); return; } - if (unlikely((skb = bcs->skb) == NULL)) { + skb = bcs->skb; + if (unlikely(skb == NULL)) { bcs->skb = skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); if (!skb) { dev_err(cs->dev, "could not allocate skb\n"); @@ -895,7 +891,8 @@ static inline void trans_receive(unsigned char *src, unsigned count, } } -void gigaset_isoc_receive(unsigned char *src, unsigned count, struct bc_state *bcs) +void gigaset_isoc_receive(unsigned char *src, unsigned count, + struct bc_state *bcs) { switch (bcs->proto2) { case L2_HDLC: -- cgit v1.2.2 From c35a87ff6678f92b12437843e88f9c89437ed4a7 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sun, 25 Oct 2009 09:30:47 +0000 Subject: gigaset: checkpatch cleanup of ev-layer.c On more step towards the holy grail of checkpatch.pl silence. Impact: cosmetic Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/ev-layer.c | 478 +++++++++++++++++++--------------------- 1 file changed, 231 insertions(+), 247 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index 369927f90729..a9a397519bac 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c @@ -40,8 +40,8 @@ /* Possible ASCII responses */ #define RSP_OK 0 -//#define RSP_BUSY 1 -//#define RSP_CONNECT 2 +#define RSP_BUSY 1 +#define RSP_CONNECT 2 #define RSP_ZGCI 3 #define RSP_RING 4 #define RSP_ZAOC 5 @@ -68,7 +68,6 @@ #define RSP_ZHLC (RSP_STR + STR_ZHLC) #define RSP_ERROR -1 /* ERROR */ #define RSP_WRONG_CID -2 /* unknown cid in cmd */ -//#define RSP_EMPTY -3 #define RSP_UNKNOWN -4 /* unknown response */ #define RSP_FAIL -5 /* internal error */ #define RSP_INVAL -6 /* invalid response */ @@ -76,9 +75,9 @@ #define RSP_NONE -19 #define RSP_STRING -20 #define RSP_NULL -21 -//#define RSP_RETRYFAIL -22 -//#define RSP_RETRY -23 -//#define RSP_SKIP -24 +#define RSP_RETRYFAIL -22 +#define RSP_RETRY -23 +#define RSP_SKIP -24 #define RSP_INIT -27 #define RSP_ANY -26 #define RSP_LAST -28 @@ -158,229 +157,225 @@ #define SEQ_UMMODE 11 -// 100: init, 200: dle0, 250:dle1, 300: get cid (dial), 350: "hup" (no cid), 400: hup, 500: reset, 600: dial, 700: ring +/* 100: init, 200: dle0, 250:dle1, 300: get cid (dial), 350: "hup" (no cid), + * 400: hup, 500: reset, 600: dial, 700: ring */ struct reply_t gigaset_tab_nocid[] = { - /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */ - - /* initialize device, set cid mode if possible */ - //{RSP_INIT, -1, -1,100, 900, 0, {ACT_TEST}}, - //{RSP_ERROR, 900,900, -1, 0, 0, {ACT_FAILINIT}}, - //{RSP_OK, 900,900, -1, 100, INIT_TIMEOUT, - // {ACT_TIMEOUT}}, - - {RSP_INIT, -1, -1,SEQ_INIT, 100, INIT_TIMEOUT, - {ACT_TIMEOUT}}, /* wait until device is ready */ - - {EV_TIMEOUT, 100,100, -1, 101, 3, {0}, "Z\r"}, /* device in transparent mode? try to initialize it. */ - {RSP_OK, 101,103, -1, 120, 5, {ACT_GETSTRING}, "+GMR\r"}, /* get version */ - - {EV_TIMEOUT, 101,101, -1, 102, 5, {0}, "Z\r"}, /* timeout => try once again. */ - {RSP_ERROR, 101,101, -1, 102, 5, {0}, "Z\r"}, /* error => try once again. */ - - {EV_TIMEOUT, 102,102, -1, 108, 5, {ACT_SETDLE1}, "^SDLE=0\r"}, /* timeout => try again in DLE mode. */ - {RSP_OK, 108,108, -1, 104,-1}, - {RSP_ZDLE, 104,104, 0, 103, 5, {0}, "Z\r"}, - {EV_TIMEOUT, 104,104, -1, 0, 0, {ACT_FAILINIT}}, - {RSP_ERROR, 108,108, -1, 0, 0, {ACT_FAILINIT}}, - - {EV_TIMEOUT, 108,108, -1, 105, 2, {ACT_SETDLE0, - ACT_HUPMODEM, - ACT_TIMEOUT}}, /* still timeout => connection in unimodem mode? */ - {EV_TIMEOUT, 105,105, -1, 103, 5, {0}, "Z\r"}, - - {RSP_ERROR, 102,102, -1, 107, 5, {0}, "^GETPRE\r"}, /* ERROR on ATZ => maybe in config mode? */ - {RSP_OK, 107,107, -1, 0, 0, {ACT_CONFIGMODE}}, - {RSP_ERROR, 107,107, -1, 0, 0, {ACT_FAILINIT}}, - {EV_TIMEOUT, 107,107, -1, 0, 0, {ACT_FAILINIT}}, - - {RSP_ERROR, 103,103, -1, 0, 0, {ACT_FAILINIT}}, - {EV_TIMEOUT, 103,103, -1, 0, 0, {ACT_FAILINIT}}, - - {RSP_STRING, 120,120, -1, 121,-1, {ACT_SETVER}}, - - {EV_TIMEOUT, 120,121, -1, 0, 0, {ACT_FAILVER, ACT_INIT}}, - {RSP_ERROR, 120,121, -1, 0, 0, {ACT_FAILVER, ACT_INIT}}, - {RSP_OK, 121,121, -1, 0, 0, {ACT_GOTVER, ACT_INIT}}, - - /* leave dle mode */ - {RSP_INIT, 0, 0,SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"}, - {RSP_OK, 201,201, -1, 202,-1}, - {RSP_ZDLE, 202,202, 0, 0, 0, {ACT_DLE0}}, - {RSP_NODEV, 200,249, -1, 0, 0, {ACT_FAKEDLE0}}, - {RSP_ERROR, 200,249, -1, 0, 0, {ACT_FAILDLE0}}, - {EV_TIMEOUT, 200,249, -1, 0, 0, {ACT_FAILDLE0}}, - - /* enter dle mode */ - {RSP_INIT, 0, 0,SEQ_DLE1, 251, 5, {0}, "^SDLE=1\r"}, - {RSP_OK, 251,251, -1, 252,-1}, - {RSP_ZDLE, 252,252, 1, 0, 0, {ACT_DLE1}}, - {RSP_ERROR, 250,299, -1, 0, 0, {ACT_FAILDLE1}}, - {EV_TIMEOUT, 250,299, -1, 0, 0, {ACT_FAILDLE1}}, - - /* incoming call */ - {RSP_RING, -1, -1, -1, -1,-1, {ACT_RING}}, - - /* get cid */ - //{RSP_INIT, 0, 0,300, 901, 0, {ACT_TEST}}, - //{RSP_ERROR, 901,901, -1, 0, 0, {ACT_FAILCID}}, - //{RSP_OK, 901,901, -1, 301, 5, {0}, "^SGCI?\r"}, - - {RSP_INIT, 0, 0,SEQ_CID, 301, 5, {0}, "^SGCI?\r"}, - {RSP_OK, 301,301, -1, 302,-1}, - {RSP_ZGCI, 302,302, -1, 0, 0, {ACT_CID}}, - {RSP_ERROR, 301,349, -1, 0, 0, {ACT_FAILCID}}, - {EV_TIMEOUT, 301,349, -1, 0, 0, {ACT_FAILCID}}, - - /* enter cid mode */ - {RSP_INIT, 0, 0,SEQ_CIDMODE, 150, 5, {0}, "^SGCI=1\r"}, - {RSP_OK, 150,150, -1, 0, 0, {ACT_CMODESET}}, - {RSP_ERROR, 150,150, -1, 0, 0, {ACT_FAILCMODE}}, - {EV_TIMEOUT, 150,150, -1, 0, 0, {ACT_FAILCMODE}}, - - /* leave cid mode */ - //{RSP_INIT, 0, 0,SEQ_UMMODE, 160, 5, {0}, "^SGCI=0\r"}, - {RSP_INIT, 0, 0,SEQ_UMMODE, 160, 5, {0}, "Z\r"}, - {RSP_OK, 160,160, -1, 0, 0, {ACT_UMODESET}}, - {RSP_ERROR, 160,160, -1, 0, 0, {ACT_FAILUMODE}}, - {EV_TIMEOUT, 160,160, -1, 0, 0, {ACT_FAILUMODE}}, - - /* abort getting cid */ - {RSP_INIT, 0, 0,SEQ_NOCID, 0, 0, {ACT_ABORTCID}}, - - /* reset */ - {RSP_INIT, 0, 0,SEQ_SHUTDOWN, 504, 5, {0}, "Z\r"}, - {RSP_OK, 504,504, -1, 0, 0, {ACT_SDOWN}}, - {RSP_ERROR, 501,599, -1, 0, 0, {ACT_FAILSDOWN}}, - {EV_TIMEOUT, 501,599, -1, 0, 0, {ACT_FAILSDOWN}}, - {RSP_NODEV, 501,599, -1, 0, 0, {ACT_FAKESDOWN}}, - - {EV_PROC_CIDMODE,-1, -1, -1, -1,-1, {ACT_PROC_CIDMODE}}, //FIXME - {EV_IF_LOCK, -1, -1, -1, -1,-1, {ACT_IF_LOCK}}, //FIXME - {EV_IF_VER, -1, -1, -1, -1,-1, {ACT_IF_VER}}, //FIXME - {EV_START, -1, -1, -1, -1,-1, {ACT_START}}, //FIXME - {EV_STOP, -1, -1, -1, -1,-1, {ACT_STOP}}, //FIXME - {EV_SHUTDOWN, -1, -1, -1, -1,-1, {ACT_SHUTDOWN}}, //FIXME - - /* misc. */ - {RSP_ERROR, -1, -1, -1, -1, -1, {ACT_ERROR} }, - {RSP_EMPTY, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME - {RSP_ZCFGT, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME - {RSP_ZCFG, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME - {RSP_ZLOG, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME - {RSP_ZMWI, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME - {RSP_ZABINFO, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME - {RSP_ZSMLSTCHG,-1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME - - {RSP_ZCAU, -1, -1, -1, -1,-1, {ACT_ZCAU}}, - {RSP_NONE, -1, -1, -1, -1,-1, {ACT_DEBUG}}, - {RSP_ANY, -1, -1, -1, -1,-1, {ACT_WARN}}, - {RSP_LAST} +/* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, + * action, command */ + +/* initialize device, set cid mode if possible */ +{RSP_INIT, -1, -1, SEQ_INIT, 100, 1, {ACT_TIMEOUT} }, + +{EV_TIMEOUT, 100, 100, -1, 101, 3, {0}, "Z\r"}, +{RSP_OK, 101, 103, -1, 120, 5, {ACT_GETSTRING}, + "+GMR\r"}, + +{EV_TIMEOUT, 101, 101, -1, 102, 5, {0}, "Z\r"}, +{RSP_ERROR, 101, 101, -1, 102, 5, {0}, "Z\r"}, + +{EV_TIMEOUT, 102, 102, -1, 108, 5, {ACT_SETDLE1}, + "^SDLE=0\r"}, +{RSP_OK, 108, 108, -1, 104, -1}, +{RSP_ZDLE, 104, 104, 0, 103, 5, {0}, "Z\r"}, +{EV_TIMEOUT, 104, 104, -1, 0, 0, {ACT_FAILINIT} }, +{RSP_ERROR, 108, 108, -1, 0, 0, {ACT_FAILINIT} }, + +{EV_TIMEOUT, 108, 108, -1, 105, 2, {ACT_SETDLE0, + ACT_HUPMODEM, + ACT_TIMEOUT} }, +{EV_TIMEOUT, 105, 105, -1, 103, 5, {0}, "Z\r"}, + +{RSP_ERROR, 102, 102, -1, 107, 5, {0}, "^GETPRE\r"}, +{RSP_OK, 107, 107, -1, 0, 0, {ACT_CONFIGMODE} }, +{RSP_ERROR, 107, 107, -1, 0, 0, {ACT_FAILINIT} }, +{EV_TIMEOUT, 107, 107, -1, 0, 0, {ACT_FAILINIT} }, + +{RSP_ERROR, 103, 103, -1, 0, 0, {ACT_FAILINIT} }, +{EV_TIMEOUT, 103, 103, -1, 0, 0, {ACT_FAILINIT} }, + +{RSP_STRING, 120, 120, -1, 121, -1, {ACT_SETVER} }, + +{EV_TIMEOUT, 120, 121, -1, 0, 0, {ACT_FAILVER, + ACT_INIT} }, +{RSP_ERROR, 120, 121, -1, 0, 0, {ACT_FAILVER, + ACT_INIT} }, +{RSP_OK, 121, 121, -1, 0, 0, {ACT_GOTVER, + ACT_INIT} }, + +/* leave dle mode */ +{RSP_INIT, 0, 0, SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"}, +{RSP_OK, 201, 201, -1, 202, -1}, +{RSP_ZDLE, 202, 202, 0, 0, 0, {ACT_DLE0} }, +{RSP_NODEV, 200, 249, -1, 0, 0, {ACT_FAKEDLE0} }, +{RSP_ERROR, 200, 249, -1, 0, 0, {ACT_FAILDLE0} }, +{EV_TIMEOUT, 200, 249, -1, 0, 0, {ACT_FAILDLE0} }, + +/* enter dle mode */ +{RSP_INIT, 0, 0, SEQ_DLE1, 251, 5, {0}, "^SDLE=1\r"}, +{RSP_OK, 251, 251, -1, 252, -1}, +{RSP_ZDLE, 252, 252, 1, 0, 0, {ACT_DLE1} }, +{RSP_ERROR, 250, 299, -1, 0, 0, {ACT_FAILDLE1} }, +{EV_TIMEOUT, 250, 299, -1, 0, 0, {ACT_FAILDLE1} }, + +/* incoming call */ +{RSP_RING, -1, -1, -1, -1, -1, {ACT_RING} }, + +/* get cid */ +{RSP_INIT, 0, 0, SEQ_CID, 301, 5, {0}, "^SGCI?\r"}, +{RSP_OK, 301, 301, -1, 302, -1}, +{RSP_ZGCI, 302, 302, -1, 0, 0, {ACT_CID} }, +{RSP_ERROR, 301, 349, -1, 0, 0, {ACT_FAILCID} }, +{EV_TIMEOUT, 301, 349, -1, 0, 0, {ACT_FAILCID} }, + +/* enter cid mode */ +{RSP_INIT, 0, 0, SEQ_CIDMODE, 150, 5, {0}, "^SGCI=1\r"}, +{RSP_OK, 150, 150, -1, 0, 0, {ACT_CMODESET} }, +{RSP_ERROR, 150, 150, -1, 0, 0, {ACT_FAILCMODE} }, +{EV_TIMEOUT, 150, 150, -1, 0, 0, {ACT_FAILCMODE} }, + +/* leave cid mode */ +{RSP_INIT, 0, 0, SEQ_UMMODE, 160, 5, {0}, "Z\r"}, +{RSP_OK, 160, 160, -1, 0, 0, {ACT_UMODESET} }, +{RSP_ERROR, 160, 160, -1, 0, 0, {ACT_FAILUMODE} }, +{EV_TIMEOUT, 160, 160, -1, 0, 0, {ACT_FAILUMODE} }, + +/* abort getting cid */ +{RSP_INIT, 0, 0, SEQ_NOCID, 0, 0, {ACT_ABORTCID} }, + +/* reset */ +{RSP_INIT, 0, 0, SEQ_SHUTDOWN, 504, 5, {0}, "Z\r"}, +{RSP_OK, 504, 504, -1, 0, 0, {ACT_SDOWN} }, +{RSP_ERROR, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} }, +{EV_TIMEOUT, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} }, +{RSP_NODEV, 501, 599, -1, 0, 0, {ACT_FAKESDOWN} }, + +{EV_PROC_CIDMODE, -1, -1, -1, -1, -1, {ACT_PROC_CIDMODE} }, +{EV_IF_LOCK, -1, -1, -1, -1, -1, {ACT_IF_LOCK} }, +{EV_IF_VER, -1, -1, -1, -1, -1, {ACT_IF_VER} }, +{EV_START, -1, -1, -1, -1, -1, {ACT_START} }, +{EV_STOP, -1, -1, -1, -1, -1, {ACT_STOP} }, +{EV_SHUTDOWN, -1, -1, -1, -1, -1, {ACT_SHUTDOWN} }, + +/* misc. */ +{RSP_ERROR, -1, -1, -1, -1, -1, {ACT_ERROR} }, +{RSP_ZCFGT, -1, -1, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ZCFG, -1, -1, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ZLOG, -1, -1, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ZMWI, -1, -1, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ZABINFO, -1, -1, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ZSMLSTCHG, -1, -1, -1, -1, -1, {ACT_DEBUG} }, + +{RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} }, +{RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} }, +{RSP_LAST} }; -// 600: start dialing, 650: dial in progress, 800: connection is up, 700: ring, 400: hup, 750: accepted icall +/* 600: start dialing, 650: dial in progress, 800: connection is up, 700: ring, + * 400: hup, 750: accepted icall */ struct reply_t gigaset_tab_cid[] = { - /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */ - - /* dial */ - {EV_DIAL, -1, -1, -1, -1,-1, {ACT_DIAL}}, //FIXME - {RSP_INIT, 0, 0,SEQ_DIAL, 601, 5, {ACT_CMD+AT_BC}}, - {RSP_OK, 601,601, -1, 602, 5, {ACT_CMD+AT_HLC}}, - {RSP_NULL, 602,602, -1, 603, 5, {ACT_CMD+AT_PROTO}}, - {RSP_OK, 602,602, -1, 603, 5, {ACT_CMD+AT_PROTO}}, - {RSP_OK, 603,603, -1, 604, 5, {ACT_CMD+AT_TYPE}}, - {RSP_OK, 604,604, -1, 605, 5, {ACT_CMD+AT_MSN}}, - {RSP_NULL, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} }, - {RSP_OK, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} }, - {RSP_NULL, 606, 606, -1, 607, 5, {ACT_CMD+AT_ISO} }, - {RSP_OK, 606, 606, -1, 607, 5, {ACT_CMD+AT_ISO} }, - {RSP_OK, 607, 607, -1, 608, 5, {0}, "+VLS=17\r"}, - {RSP_OK, 608, 608, -1, 609, -1}, - {RSP_ZSAU, 609, 609, ZSAU_PROCEEDING, 610, 5, {ACT_CMD+AT_DIAL} }, - {RSP_OK, 610, 610, -1, 650, 0, {ACT_DIALING} }, - - {RSP_ERROR, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} }, - {EV_TIMEOUT, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} }, - - /* optional dialing responses */ - {EV_BC_OPEN, 650,650, -1, 651,-1}, - {RSP_ZVLS, 609, 651, 17, -1, -1, {ACT_DEBUG} }, - {RSP_ZCTP, 610, 651, -1, -1, -1, {ACT_DEBUG} }, - {RSP_ZCPN, 610, 651, -1, -1, -1, {ACT_DEBUG} }, - {RSP_ZSAU, 650,651,ZSAU_CALL_DELIVERED, -1,-1, {ACT_DEBUG}}, - - /* connect */ - {RSP_ZSAU, 650,650,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, - {RSP_ZSAU, 651,651,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT, - ACT_NOTIFY_BC_UP}}, - {RSP_ZSAU, 750,750,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, - {RSP_ZSAU, 751,751,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT, - ACT_NOTIFY_BC_UP}}, - {EV_BC_OPEN, 800,800, -1, 800,-1, {ACT_NOTIFY_BC_UP}}, - - /* remote hangup */ - {RSP_ZSAU, 650,651,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT}}, - {RSP_ZSAU, 750,751,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}}, - {RSP_ZSAU, 800,800,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}}, - - /* hangup */ - {EV_HUP, -1, -1, -1, -1,-1, {ACT_HUP}}, //FIXME - {RSP_INIT, -1, -1,SEQ_HUP, 401, 5, {0}, "+VLS=0\r"}, /* hang up */ //-1,-1? - {RSP_OK, 401,401, -1, 402, 5}, - {RSP_ZVLS, 402,402, 0, 403, 5}, - {RSP_ZSAU, 403, 403, ZSAU_DISCONNECT_REQ, -1, -1, {ACT_DEBUG} }, - {RSP_ZSAU, 403, 403, ZSAU_NULL, 0, 0, {ACT_DISCONNECT} }, - {RSP_NODEV, 401, 403, -1, 0, 0, {ACT_FAKEHUP} }, - {RSP_ERROR, 401,401, -1, 0, 0, {ACT_ABORTHUP}}, - {EV_TIMEOUT, 401,403, -1, 0, 0, {ACT_ABORTHUP}}, - - {EV_BC_CLOSED, 0, 0, -1, 0,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME new constate + timeout - - /* ring */ - {RSP_ZBC, 700,700, -1, -1,-1, {0}}, - {RSP_ZHLC, 700,700, -1, -1,-1, {0}}, - {RSP_NMBR, 700,700, -1, -1,-1, {0}}, - {RSP_ZCPN, 700,700, -1, -1,-1, {0}}, - {RSP_ZCTP, 700,700, -1, -1,-1, {0}}, - {EV_TIMEOUT, 700,700, -1, 720,720, {ACT_ICALL}}, - {EV_BC_CLOSED,720,720, -1, 0,-1, {ACT_NOTIFY_BC_DOWN}}, - - /*accept icall*/ - {EV_ACCEPT, -1, -1, -1, -1,-1, {ACT_ACCEPT}}, //FIXME - {RSP_INIT, 720,720,SEQ_ACCEPT, 721, 5, {ACT_CMD+AT_PROTO}}, - {RSP_OK, 721,721, -1, 722, 5, {ACT_CMD+AT_ISO}}, - {RSP_OK, 722,722, -1, 723, 5, {0}, "+VLS=17\r"}, /* set "Endgeraetemodus" */ - {RSP_OK, 723,723, -1, 724, 5, {0}}, - {RSP_ZVLS, 724,724, 17, 750,50, {ACT_ACCEPTED}}, - {RSP_ERROR, 721,729, -1, 0, 0, {ACT_ABORTACCEPT}}, - {EV_TIMEOUT, 721,729, -1, 0, 0, {ACT_ABORTACCEPT}}, - {RSP_ZSAU, 700,729,ZSAU_NULL, 0, 0, {ACT_ABORTACCEPT}}, - {RSP_ZSAU, 700,729,ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT}}, - {RSP_ZSAU, 700,729,ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT}}, - - {EV_BC_OPEN, 750,750, -1, 751,-1}, - {EV_TIMEOUT, 750,751, -1, 0, 0, {ACT_CONNTIMEOUT}}, - - /* B channel closed (general case) */ - {EV_BC_CLOSED, -1, -1, -1, -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME - - /* misc. */ - {RSP_ZCON, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME - {RSP_ZCCR, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME - {RSP_ZAOC, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME - {RSP_ZCSTR, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME - - {RSP_ZCAU, -1, -1, -1, -1,-1, {ACT_ZCAU}}, - {RSP_NONE, -1, -1, -1, -1,-1, {ACT_DEBUG}}, - {RSP_ANY, -1, -1, -1, -1,-1, {ACT_WARN}}, - {RSP_LAST} +/* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, + * action, command */ + +/* dial */ +{EV_DIAL, -1, -1, -1, -1, -1, {ACT_DIAL} }, +{RSP_INIT, 0, 0, SEQ_DIAL, 601, 5, {ACT_CMD+AT_BC} }, +{RSP_OK, 601, 601, -1, 602, 5, {ACT_CMD+AT_HLC} }, +{RSP_NULL, 602, 602, -1, 603, 5, {ACT_CMD+AT_PROTO} }, +{RSP_OK, 602, 602, -1, 603, 5, {ACT_CMD+AT_PROTO} }, +{RSP_OK, 603, 603, -1, 604, 5, {ACT_CMD+AT_TYPE} }, +{RSP_OK, 604, 604, -1, 605, 5, {ACT_CMD+AT_MSN} }, +{RSP_NULL, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} }, +{RSP_OK, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} }, +{RSP_NULL, 606, 606, -1, 607, 5, {ACT_CMD+AT_ISO} }, +{RSP_OK, 606, 606, -1, 607, 5, {ACT_CMD+AT_ISO} }, +{RSP_OK, 607, 607, -1, 608, 5, {0}, "+VLS=17\r"}, +{RSP_OK, 608, 608, -1, 609, -1}, +{RSP_ZSAU, 609, 609, ZSAU_PROCEEDING, 610, 5, {ACT_CMD+AT_DIAL} }, +{RSP_OK, 610, 610, -1, 650, 0, {ACT_DIALING} }, + +{RSP_ERROR, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} }, +{EV_TIMEOUT, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} }, + +/* optional dialing responses */ +{EV_BC_OPEN, 650, 650, -1, 651, -1}, +{RSP_ZVLS, 609, 651, 17, -1, -1, {ACT_DEBUG} }, +{RSP_ZCTP, 610, 651, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ZCPN, 610, 651, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ZSAU, 650, 651, ZSAU_CALL_DELIVERED, -1, -1, {ACT_DEBUG} }, + +/* connect */ +{RSP_ZSAU, 650, 650, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} }, +{RSP_ZSAU, 651, 651, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT, + ACT_NOTIFY_BC_UP} }, +{RSP_ZSAU, 750, 750, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} }, +{RSP_ZSAU, 751, 751, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT, + ACT_NOTIFY_BC_UP} }, +{EV_BC_OPEN, 800, 800, -1, 800, -1, {ACT_NOTIFY_BC_UP} }, + +/* remote hangup */ +{RSP_ZSAU, 650, 651, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT} }, +{RSP_ZSAU, 750, 751, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} }, +{RSP_ZSAU, 800, 800, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} }, + +/* hangup */ +{EV_HUP, -1, -1, -1, -1, -1, {ACT_HUP} }, +{RSP_INIT, -1, -1, SEQ_HUP, 401, 5, {0}, "+VLS=0\r"}, +{RSP_OK, 401, 401, -1, 402, 5}, +{RSP_ZVLS, 402, 402, 0, 403, 5}, +{RSP_ZSAU, 403, 403, ZSAU_DISCONNECT_REQ, -1, -1, {ACT_DEBUG} }, +{RSP_ZSAU, 403, 403, ZSAU_NULL, 0, 0, {ACT_DISCONNECT} }, +{RSP_NODEV, 401, 403, -1, 0, 0, {ACT_FAKEHUP} }, +{RSP_ERROR, 401, 401, -1, 0, 0, {ACT_ABORTHUP} }, +{EV_TIMEOUT, 401, 403, -1, 0, 0, {ACT_ABORTHUP} }, + +{EV_BC_CLOSED, 0, 0, -1, 0, -1, {ACT_NOTIFY_BC_DOWN} }, + +/* ring */ +{RSP_ZBC, 700, 700, -1, -1, -1, {0} }, +{RSP_ZHLC, 700, 700, -1, -1, -1, {0} }, +{RSP_NMBR, 700, 700, -1, -1, -1, {0} }, +{RSP_ZCPN, 700, 700, -1, -1, -1, {0} }, +{RSP_ZCTP, 700, 700, -1, -1, -1, {0} }, +{EV_TIMEOUT, 700, 700, -1, 720, 720, {ACT_ICALL} }, +{EV_BC_CLOSED, 720, 720, -1, 0, -1, {ACT_NOTIFY_BC_DOWN} }, + +/*accept icall*/ +{EV_ACCEPT, -1, -1, -1, -1, -1, {ACT_ACCEPT} }, +{RSP_INIT, 720, 720, SEQ_ACCEPT, 721, 5, {ACT_CMD+AT_PROTO} }, +{RSP_OK, 721, 721, -1, 722, 5, {ACT_CMD+AT_ISO} }, +{RSP_OK, 722, 722, -1, 723, 5, {0}, "+VLS=17\r"}, +{RSP_OK, 723, 723, -1, 724, 5, {0} }, +{RSP_ZVLS, 724, 724, 17, 750, 50, {ACT_ACCEPTED} }, +{RSP_ERROR, 721, 729, -1, 0, 0, {ACT_ABORTACCEPT} }, +{EV_TIMEOUT, 721, 729, -1, 0, 0, {ACT_ABORTACCEPT} }, +{RSP_ZSAU, 700, 729, ZSAU_NULL, 0, 0, {ACT_ABORTACCEPT} }, +{RSP_ZSAU, 700, 729, ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT} }, +{RSP_ZSAU, 700, 729, ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT} }, + +{EV_BC_OPEN, 750, 750, -1, 751, -1}, +{EV_TIMEOUT, 750, 751, -1, 0, 0, {ACT_CONNTIMEOUT} }, + +/* B channel closed (general case) */ +{EV_BC_CLOSED, -1, -1, -1, -1, -1, {ACT_NOTIFY_BC_DOWN} }, + +/* misc. */ +{RSP_ZCON, -1, -1, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ZCCR, -1, -1, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ZAOC, -1, -1, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ZCSTR, -1, -1, -1, -1, -1, {ACT_DEBUG} }, + +{RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} }, +{RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} }, +{RSP_LAST} }; static const struct resp_type_t resp_type[] = { - /*{"", RSP_EMPTY, RT_NOTHING},*/ {"OK", RSP_OK, RT_NOTHING}, {"ERROR", RSP_ERROR, RT_NOTHING}, {"ZSAU", RSP_ZSAU, RT_ZSAU}, @@ -404,7 +399,7 @@ static const struct resp_type_t resp_type[] = {"ZLOG", RSP_ZLOG, RT_NOTHING}, {"ZABINFO", RSP_ZABINFO, RT_NOTHING}, {"ZSMLSTCHG", RSP_ZSMLSTCHG, RT_NOTHING}, - {NULL,0,0} + {NULL, 0, 0} }; /* @@ -469,7 +464,6 @@ static int cid_of_response(char *s) if (cid < 1 || cid > 65535) return -1; /* CID out of range */ return cid; - //FIXME is ;+ at end of non-CID response really impossible? } /** @@ -613,7 +607,8 @@ void gigaset_handle_modem_response(struct cardstate *cs) break; } if (!strcmp(argv[curarg], "OUTGOING_CALL_PROCEEDING")) - event->parameter = ZSAU_OUTGOING_CALL_PROCEEDING; + event->parameter = + ZSAU_OUTGOING_CALL_PROCEEDING; else if (!strcmp(argv[curarg], "CALL_DELIVERED")) event->parameter = ZSAU_CALL_DELIVERED; else if (!strcmp(argv[curarg], "ACTIVE")) @@ -896,7 +891,8 @@ static void bchannel_up(struct bc_state *bcs) gigaset_isdn_connB(bcs); } -static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_index) +static void start_dial(struct at_state_t *at_state, void *data, + unsigned seq_index) { struct bc_state *bcs = at_state->bcs; struct cardstate *cs = at_state->cs; @@ -973,8 +969,6 @@ static void do_start(struct cardstate *cs) cs->isdn_up = 1; gigaset_isdn_start(cs); - // FIXME: not in locked mode - // FIXME 2: only after init sequence cs->waiting = 0; wake_up(&cs->waitqueue); @@ -1128,7 +1122,6 @@ static int do_lock(struct cardstate *cs) break; case MS_LOCKED: - //retval = -EACCES; break; default: return -EBUSY; @@ -1384,7 +1377,7 @@ static void do_action(int action, struct cardstate *cs, cs->cur_at_seq = SEQ_NONE; break; - case ACT_ABORTACCEPT: /* hangup/error/timeout during ICALL processing */ + case ACT_ABORTACCEPT: /* hangup/error/timeout during ICALL procssng */ disconnect(p_at_state); break; @@ -1458,17 +1451,6 @@ static void do_action(int action, struct cardstate *cs, __func__, at_state->ConState); cs->cur_at_seq = SEQ_NONE; break; -#ifdef CONFIG_GIGASET_DEBUG - case ACT_TEST: - { - static int count = 3; //2; //1; - *p_genresp = 1; - *p_resp_code = count ? RSP_ERROR : RSP_OK; - if (count > 0) - --count; - } - break; -#endif case ACT_DEBUG: gig_dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d", __func__, ev->type, at_state->ConState); @@ -1503,7 +1485,7 @@ static void do_action(int action, struct cardstate *cs, do_start(cs); break; - /* events from the interface */ // FIXME without ACT_xxxx? + /* events from the interface */ case ACT_IF_LOCK: cs->cmd_result = ev->parameter ? do_lock(cs) : do_unlock(cs); cs->waiting = 0; @@ -1522,7 +1504,7 @@ static void do_action(int action, struct cardstate *cs, wake_up(&cs->waitqueue); break; - /* events from the proc file system */ // FIXME without ACT_xxxx? + /* events from the proc file system */ case ACT_PROC_CIDMODE: spin_lock_irqsave(&cs->lock, flags); if (ev->parameter != cs->cidmode) { @@ -1659,7 +1641,8 @@ static void process_event(struct cardstate *cs, struct event_t *ev) for (curact = 0; curact < MAXACT; ++curact) { /* The row tells us what we should do .. */ - do_action(rep->action[curact], cs, bcs, &at_state, &p_command, &genresp, &resp_code, ev); + do_action(rep->action[curact], cs, bcs, &at_state, &p_command, + &genresp, &resp_code, ev); if (!at_state) break; /* may be freed after disconnect */ } @@ -1671,13 +1654,14 @@ static void process_event(struct cardstate *cs, struct event_t *ev) if (genresp) { spin_lock_irqsave(&cs->lock, flags); - at_state->timer_expires = 0; //FIXME - at_state->timer_active = 0; //FIXME + at_state->timer_expires = 0; + at_state->timer_active = 0; spin_unlock_irqrestore(&cs->lock, flags); - gigaset_add_event(cs, at_state, resp_code, NULL, 0, NULL); + gigaset_add_event(cs, at_state, resp_code, + NULL, 0, NULL); } else { /* Send command to modem if not NULL... */ - if (p_command/*rep->command*/) { + if (p_command) { if (cs->connected) send_command(cs, p_command, sendcid, cs->dle, @@ -1764,7 +1748,8 @@ static void process_command_flags(struct cardstate *cs) } } - /* only switch back to unimodem mode, if no commands are pending and no channels are up */ + /* only switch back to unimodem mode if no commands are pending and + * no channels are up */ spin_lock_irqsave(&cs->lock, flags); if (cs->at_state.pending_commands == PC_UMMODE && !cs->cidmode @@ -1823,9 +1808,8 @@ static void process_command_flags(struct cardstate *cs) if (cs->at_state.pending_commands & PC_INIT) { cs->at_state.pending_commands &= ~PC_INIT; - cs->dle = 0; //FIXME + cs->dle = 0; cs->inbuf->inputstate = INS_command; - //FIXME reset card state (or -> LOCK0)? schedule_sequence(cs, &cs->at_state, SEQ_INIT); return; } -- cgit v1.2.2 From 50e4fe91a5edbf680853b2ca37300a47ff860d63 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sun, 25 Oct 2009 09:30:57 +0000 Subject: gigaset: convert strcmp chain to table lookup Replace the sequence of strcmp calls for interpreting ZSAU parameter strings by a table of known strings and lookup loop to improve readability. Impact: readability improvement, no functional change Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/ev-layer.c | 42 ++++++++++++++++++++++++----------------- drivers/isdn/gigaset/gigaset.h | 6 ------ 2 files changed, 25 insertions(+), 23 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index a9a397519bac..ddeb0456d202 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c @@ -374,7 +374,11 @@ struct reply_t gigaset_tab_cid[] = }; -static const struct resp_type_t resp_type[] = +static const struct resp_type_t { + unsigned char *response; + int resp_code; + int type; +} resp_type[] = { {"OK", RSP_OK, RT_NOTHING}, {"ERROR", RSP_ERROR, RT_NOTHING}, @@ -402,6 +406,20 @@ static const struct resp_type_t resp_type[] = {NULL, 0, 0} }; +static const struct zsau_resp_t { + unsigned char *str; + int code; +} zsau_resp[] = +{ + {"OUTGOING_CALL_PROCEEDING", ZSAU_OUTGOING_CALL_PROCEEDING}, + {"CALL_DELIVERED", ZSAU_CALL_DELIVERED}, + {"ACTIVE", ZSAU_ACTIVE}, + {"DISCONNECT_IND", ZSAU_DISCONNECT_IND}, + {"NULL", ZSAU_NULL}, + {"DISCONNECT_REQ", ZSAU_DISCONNECT_REQ}, + {NULL, ZSAU_UNKNOWN} +}; + /* * Get integer from char-pointer */ @@ -480,6 +498,7 @@ void gigaset_handle_modem_response(struct cardstate *cs) int params; int i, j; const struct resp_type_t *rt; + const struct zsau_resp_t *zr; int curarg; unsigned long flags; unsigned next, tail, head; @@ -606,25 +625,14 @@ void gigaset_handle_modem_response(struct cardstate *cs) event->parameter = ZSAU_NONE; break; } - if (!strcmp(argv[curarg], "OUTGOING_CALL_PROCEEDING")) - event->parameter = - ZSAU_OUTGOING_CALL_PROCEEDING; - else if (!strcmp(argv[curarg], "CALL_DELIVERED")) - event->parameter = ZSAU_CALL_DELIVERED; - else if (!strcmp(argv[curarg], "ACTIVE")) - event->parameter = ZSAU_ACTIVE; - else if (!strcmp(argv[curarg], "DISCONNECT_IND")) - event->parameter = ZSAU_DISCONNECT_IND; - else if (!strcmp(argv[curarg], "NULL")) - event->parameter = ZSAU_NULL; - else if (!strcmp(argv[curarg], "DISCONNECT_REQ")) - event->parameter = ZSAU_DISCONNECT_REQ; - else { - event->parameter = ZSAU_UNKNOWN; + for (zr = zsau_resp; zr->str; ++zr) + if (!strcmp(argv[curarg], zr->str)) + break; + event->parameter = zr->code; + if (!zr->str) dev_warn(cs->dev, "%s: unknown parameter %s after ZSAU\n", __func__, argv[curarg]); - } ++curarg; break; case RT_STRING: diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 3c74cd164019..e963a6c2e86d 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -357,12 +357,6 @@ struct at_state_t { struct bc_state *bcs; }; -struct resp_type_t { - unsigned char *response; - int resp_code; /* RSP_XXXX */ - int type; /* RT_XXXX */ -}; - struct event_t { int type; void *ptr, *arg; -- cgit v1.2.2 From 3f378b684453f2a028eda463ce383370545d9cc9 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 5 Nov 2009 22:18:14 -0800 Subject: net: pass kern to net_proto_family create function The generic __sock_create function has a kern argument which allows the security system to make decisions based on if a socket is being created by the kernel or by userspace. This patch passes that flag to the net_proto_family specific create function, so it can do the same thing. Signed-off-by: Eric Paris Acked-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- drivers/isdn/mISDN/socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c index 28182ed8dea1..fcfe17a19a61 100644 --- a/drivers/isdn/mISDN/socket.c +++ b/drivers/isdn/mISDN/socket.c @@ -779,7 +779,7 @@ base_sock_create(struct net *net, struct socket *sock, int protocol) } static int -mISDN_sock_create(struct net *net, struct socket *sock, int proto) +mISDN_sock_create(struct net *net, struct socket *sock, int proto, int kern) { int err = -EPROTONOSUPPORT; -- cgit v1.2.2 From e773cfe167c320d07b9423bc51fc4ab0221775a4 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sat, 24 Oct 2009 15:50:13 +0200 Subject: pcmcia: use dynamic debug infrastructure, deprecate CS_CHECK (isdn) Convert PCMCIA drivers to use the dynamic debug infrastructure, instead of requiring manual settings of PCMCIA_DEBUG. Also, remove all usages of the CS_CHECK macro and replace them with proper Linux style calling and return value checking. The extra error reporting may be dropped, as the PCMCIA core already complains about any (non-driver-author) errors. CC: Karsten Keil Signed-off-by: Dominik Brodowski --- drivers/isdn/hardware/avm/avm_cs.c | 2 -- drivers/isdn/hisax/avma1_cs.c | 26 +++-------------- drivers/isdn/hisax/elsa_cs.c | 45 +++++++---------------------- drivers/isdn/hisax/sedlbauer_cs.c | 59 ++++++++++++++------------------------ drivers/isdn/hisax/teles_cs.c | 37 +++++------------------- 5 files changed, 43 insertions(+), 126 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index c72565520e41..d388eadb9fdb 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c @@ -198,7 +198,6 @@ static int avmcs_config(struct pcmcia_device *link) */ i = pcmcia_request_irq(link, &link->irq); if (i != 0) { - cs_error(link, RequestIRQ, i); /* undo */ pcmcia_disable_device(link); break; @@ -209,7 +208,6 @@ static int avmcs_config(struct pcmcia_device *link) */ i = pcmcia_request_configuration(link, &link->conf); if (i != 0) { - cs_error(link, RequestConfiguration, i); pcmcia_disable_device(link); break; } diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index 23560c897ec3..6d963f9a09ce 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c @@ -30,22 +30,6 @@ MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for AVM A1/Fritz!PCMCIA car MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); -/* - All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If - you do not define PCMCIA_DEBUG at all, all the debug code will be - left out. If you compile with PCMCIA_DEBUG=0, the debug code will - be present but disabled -- but it can then be enabled for specific - modules at load time with a 'pc_debug=#' option to insmod. -*/ -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); -static char *version = -"avma1_cs.c 1.00 1998/01/23 10:00:00 (Carsten Paeth)"; -#else -#define DEBUG(n, args...) -#endif /*====================================================================*/ @@ -119,7 +103,7 @@ static int avma1cs_probe(struct pcmcia_device *p_dev) { local_info_t *local; - DEBUG(0, "avma1cs_attach()\n"); + dev_dbg(&p_dev->dev, "avma1cs_attach()\n"); /* Allocate space for private device-specific data */ local = kzalloc(sizeof(local_info_t), GFP_KERNEL); @@ -161,7 +145,7 @@ static int avma1cs_probe(struct pcmcia_device *p_dev) static void avma1cs_detach(struct pcmcia_device *link) { - DEBUG(0, "avma1cs_detach(0x%p)\n", link); + dev_dbg(&link->dev, "avma1cs_detach(0x%p)\n", link); avma1cs_release(link); kfree(link->priv); } /* avma1cs_detach */ @@ -203,7 +187,7 @@ static int avma1cs_config(struct pcmcia_device *link) dev = link->priv; - DEBUG(0, "avma1cs_config(0x%p)\n", link); + dev_dbg(&link->dev, "avma1cs_config(0x%p)\n", link); devname[0] = 0; if (link->prod_id[1]) @@ -218,7 +202,6 @@ static int avma1cs_config(struct pcmcia_device *link) */ i = pcmcia_request_irq(link, &link->irq); if (i != 0) { - cs_error(link, RequestIRQ, i); /* undo */ pcmcia_disable_device(link); break; @@ -229,7 +212,6 @@ static int avma1cs_config(struct pcmcia_device *link) */ i = pcmcia_request_configuration(link, &link->conf); if (i != 0) { - cs_error(link, RequestConfiguration, i); pcmcia_disable_device(link); break; } @@ -281,7 +263,7 @@ static void avma1cs_release(struct pcmcia_device *link) { local_info_t *local = link->priv; - DEBUG(0, "avma1cs_release(0x%p)\n", link); + dev_dbg(&link->dev, "avma1cs_release(0x%p)\n", link); /* now unregister function with hisax */ HiSax_closecard(local->node.minor); diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index f4d0fe29bcf8..cdcd2979fcd4 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -57,23 +57,6 @@ MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Elsa PCM cards"); MODULE_AUTHOR("Klaus Lichtenwalder"); MODULE_LICENSE("Dual MPL/GPL"); -/* - All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If - you do not define PCMCIA_DEBUG at all, all the debug code will be - left out. If you compile with PCMCIA_DEBUG=0, the debug code will - be present but disabled -- but it can then be enabled for specific - modules at load time with a 'pc_debug=#' option to insmod. -*/ - -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); -static char *version = -"elsa_cs.c $Revision: 1.2.2.4 $ $Date: 2004/01/25 15:07:06 $ (K.Lichtenwalder)"; -#else -#define DEBUG(n, args...) -#endif /*====================================================================*/ @@ -142,7 +125,7 @@ static int elsa_cs_probe(struct pcmcia_device *link) { local_info_t *local; - DEBUG(0, "elsa_cs_attach()\n"); + dev_dbg(&link->dev, "elsa_cs_attach()\n"); /* Allocate space for private device-specific data */ local = kzalloc(sizeof(local_info_t), GFP_KERNEL); @@ -188,7 +171,7 @@ static void elsa_cs_detach(struct pcmcia_device *link) { local_info_t *info = link->priv; - DEBUG(0, "elsa_cs_detach(0x%p)\n", link); + dev_dbg(&link->dev, "elsa_cs_detach(0x%p)\n", link); info->busy = 1; elsa_cs_release(link); @@ -231,30 +214,25 @@ static int elsa_cs_configcheck(struct pcmcia_device *p_dev, static int elsa_cs_config(struct pcmcia_device *link) { local_info_t *dev; - int i, last_fn; + int i; IsdnCard_t icard; - DEBUG(0, "elsa_config(0x%p)\n", link); + dev_dbg(&link->dev, "elsa_config(0x%p)\n", link); dev = link->priv; i = pcmcia_loop_config(link, elsa_cs_configcheck, NULL); - if (i != 0) { - last_fn = RequestIO; - goto cs_failed; - } + if (i != 0) + goto failed; i = pcmcia_request_irq(link, &link->irq); if (i != 0) { link->irq.AssignedIRQ = 0; - last_fn = RequestIRQ; - goto cs_failed; + goto failed; } i = pcmcia_request_configuration(link, &link->conf); - if (i != 0) { - last_fn = RequestConfiguration; - goto cs_failed; - } + if (i != 0) + goto failed; /* At this point, the dev_node_t structure(s) should be initialized and arranged in a linked list at link->dev. *//* */ @@ -290,8 +268,7 @@ static int elsa_cs_config(struct pcmcia_device *link) ((local_info_t*)link->priv)->cardnr = i; return 0; -cs_failed: - cs_error(link, last_fn, i); +failed: elsa_cs_release(link); return -ENODEV; } /* elsa_cs_config */ @@ -308,7 +285,7 @@ static void elsa_cs_release(struct pcmcia_device *link) { local_info_t *local = link->priv; - DEBUG(0, "elsa_cs_release(0x%p)\n", link); + dev_dbg(&link->dev, "elsa_cs_release(0x%p)\n", link); if (local) { if (local->cardnr >= 0) { diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index 9a3c9f5e4fe8..33d7530527c7 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -57,24 +57,6 @@ MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Sedlbauer cards"); MODULE_AUTHOR("Marcus Niemann"); MODULE_LICENSE("Dual MPL/GPL"); -/* - All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If - you do not define PCMCIA_DEBUG at all, all the debug code will be - left out. If you compile with PCMCIA_DEBUG=0, the debug code will - be present but disabled -- but it can then be enabled for specific - modules at load time with a 'pc_debug=#' option to insmod. -*/ - -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); -static char *version = -"sedlbauer_cs.c 1.1a 2001/01/28 15:04:04 (M.Niemann)"; -#else -#define DEBUG(n, args...) -#endif - /*====================================================================*/ @@ -151,7 +133,7 @@ static int sedlbauer_probe(struct pcmcia_device *link) { local_info_t *local; - DEBUG(0, "sedlbauer_attach()\n"); + dev_dbg(&link->dev, "sedlbauer_attach()\n"); /* Allocate space for private device-specific data */ local = kzalloc(sizeof(local_info_t), GFP_KERNEL); @@ -198,7 +180,7 @@ static int sedlbauer_probe(struct pcmcia_device *link) static void sedlbauer_detach(struct pcmcia_device *link) { - DEBUG(0, "sedlbauer_detach(0x%p)\n", link); + dev_dbg(&link->dev, "sedlbauer_detach(0x%p)\n", link); ((local_info_t *)link->priv)->stop = 1; sedlbauer_release(link); @@ -214,9 +196,6 @@ static void sedlbauer_detach(struct pcmcia_device *link) device available to the system. ======================================================================*/ -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) - static int sedlbauer_config_check(struct pcmcia_device *p_dev, cistpl_cftable_entry_t *cfg, cistpl_cftable_entry_t *dflt, @@ -309,10 +288,10 @@ static int sedlbauer_config(struct pcmcia_device *link) { local_info_t *dev = link->priv; win_req_t *req; - int last_fn, last_ret; + int ret; IsdnCard_t icard; - DEBUG(0, "sedlbauer_config(0x%p)\n", link); + dev_dbg(&link->dev, "sedlbauer_config(0x%p)\n", link); req = kzalloc(sizeof(win_req_t), GFP_KERNEL); if (!req) @@ -330,8 +309,8 @@ static int sedlbauer_config(struct pcmcia_device *link) these things without consulting the CIS, and most client drivers will only use the CIS to fill in implementation-defined details. */ - last_ret = pcmcia_loop_config(link, sedlbauer_config_check, req); - if (last_ret) + ret = pcmcia_loop_config(link, sedlbauer_config_check, req); + if (ret) goto failed; /* @@ -339,15 +318,20 @@ static int sedlbauer_config(struct pcmcia_device *link) handler to the interrupt, unless the 'Handler' member of the irq structure is initialized. */ - if (link->conf.Attributes & CONF_ENABLE_IRQ) - CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); + if (link->conf.Attributes & CONF_ENABLE_IRQ) { + ret = pcmcia_request_irq(link, &link->irq); + if (ret) + goto failed; + } /* This actually configures the PCMCIA socket -- setting up the I/O windows and the interrupt mapping, and putting the card and host interface into "Memory and IO" mode. */ - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); + ret = pcmcia_request_configuration(link, &link->conf); + if (ret) + goto failed; /* At this point, the dev_node_t structure(s) need to be @@ -380,19 +364,18 @@ static int sedlbauer_config(struct pcmcia_device *link) icard.protocol = protocol; icard.typ = ISDN_CTYPE_SEDLBAUER_PCMCIA; - last_ret = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->stop), &icard); - if (last_ret < 0) { - printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n", - last_ret, link->io.BasePort1); + ret = hisax_init_pcmcia(link, + &(((local_info_t *)link->priv)->stop), &icard); + if (ret < 0) { + printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n", + ret, link->io.BasePort1); sedlbauer_release(link); return -ENODEV; } else - ((local_info_t*)link->priv)->cardnr = last_ret; + ((local_info_t *)link->priv)->cardnr = ret; return 0; -cs_failed: - cs_error(link, last_fn, last_ret); failed: sedlbauer_release(link); return -ENODEV; @@ -410,7 +393,7 @@ failed: static void sedlbauer_release(struct pcmcia_device *link) { local_info_t *local = link->priv; - DEBUG(0, "sedlbauer_release(0x%p)\n", link); + dev_dbg(&link->dev, "sedlbauer_release(0x%p)\n", link); if (local) { if (local->cardnr >= 0) { diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index 623d111544d4..7b11c15b3a97 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c @@ -38,23 +38,6 @@ MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Teles PCMCIA cards"); MODULE_AUTHOR("Christof Petig, christof.petig@wtal.de, Karsten Keil, kkeil@suse.de"); MODULE_LICENSE("GPL"); -/* - All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If - you do not define PCMCIA_DEBUG at all, all the debug code will be - left out. If you compile with PCMCIA_DEBUG=0, the debug code will - be present but disabled -- but it can then be enabled for specific - modules at load time with a 'pc_debug=#' option to insmod. -*/ - -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); -static char *version = -"teles_cs.c 2.10 2002/07/30 22:23:34 kkeil"; -#else -#define DEBUG(n, args...) -#endif /*====================================================================*/ @@ -133,7 +116,7 @@ static int teles_probe(struct pcmcia_device *link) { local_info_t *local; - DEBUG(0, "teles_attach()\n"); + dev_dbg(&link->dev, "teles_attach()\n"); /* Allocate space for private device-specific data */ local = kzalloc(sizeof(local_info_t), GFP_KERNEL); @@ -178,7 +161,7 @@ static void teles_detach(struct pcmcia_device *link) { local_info_t *info = link->priv; - DEBUG(0, "teles_detach(0x%p)\n", link); + dev_dbg(&link->dev, "teles_detach(0x%p)\n", link); info->busy = 1; teles_cs_release(link); @@ -221,30 +204,25 @@ static int teles_cs_configcheck(struct pcmcia_device *p_dev, static int teles_cs_config(struct pcmcia_device *link) { local_info_t *dev; - int i, last_fn; + int i; IsdnCard_t icard; - DEBUG(0, "teles_config(0x%p)\n", link); + dev_dbg(&link->dev, "teles_config(0x%p)\n", link); dev = link->priv; i = pcmcia_loop_config(link, teles_cs_configcheck, NULL); - if (i != 0) { - last_fn = RequestIO; + if (i != 0) goto cs_failed; - } i = pcmcia_request_irq(link, &link->irq); if (i != 0) { link->irq.AssignedIRQ = 0; - last_fn = RequestIRQ; goto cs_failed; } i = pcmcia_request_configuration(link, &link->conf); - if (i != 0) { - last_fn = RequestConfiguration; + if (i != 0) goto cs_failed; - } /* At this point, the dev_node_t structure(s) should be initialized and arranged in a linked list at link->dev. *//* */ @@ -283,7 +261,6 @@ static int teles_cs_config(struct pcmcia_device *link) return 0; cs_failed: - cs_error(link, last_fn, i); teles_cs_release(link); return -ENODEV; } /* teles_cs_config */ @@ -300,7 +277,7 @@ static void teles_cs_release(struct pcmcia_device *link) { local_info_t *local = link->priv; - DEBUG(0, "teles_cs_release(0x%p)\n", link); + dev_dbg(&link->dev, "teles_cs_release(0x%p)\n", link); if (local) { if (local->cardnr >= 0) { -- cgit v1.2.2 From 06fe9fb4182177fb046e6d934f80254dd90956ea Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Mon, 28 Sep 2009 21:43:57 -0400 Subject: tree-wide: fix a very frequent spelling mistake something-bility is spelled as something-blity so a grep for 'blit' would find these lines this is so trivial that I didn't split it by subsystem / copy additional maintainers - all changes are to comments The only purpose is to get fewer false positives when grepping around the kernel sources. Signed-off-by: Dirk Hohndel Signed-off-by: Jiri Kosina --- drivers/isdn/i4l/isdn_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index 90b56ed8651f..507e13d9a57c 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c @@ -1563,7 +1563,7 @@ isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data) *(__be32 *)(p + 4) = cpu_to_be32(CISCO_SLARP_KEEPALIVE); *(__be32 *)(p + 8) = cpu_to_be32(lp->cisco_myseq); *(__be32 *)(p + 12) = cpu_to_be32(lp->cisco_yourseq); - *(__be16 *)(p + 16) = cpu_to_be16(0xffff); // reliablity, always 0xffff + *(__be16 *)(p + 16) = cpu_to_be16(0xffff); // reliability, always 0xffff p += 18; isdn_net_write_super(lp, skb); -- cgit v1.2.2 From fa3012318bfb395552baef69bb1ebe87e64945c8 Mon Sep 17 00:00:00 2001 From: Michael Roth Date: Sun, 4 Oct 2009 18:14:29 +0200 Subject: Kconfig: Remove useless and sometimes wrong comments Additionally, some excessive newlines removed. Signed-off-by: Michael Roth Signed-off-by: Jiri Kosina --- drivers/isdn/act2000/Kconfig | 4 ---- drivers/isdn/capi/Kconfig | 4 ---- drivers/isdn/hysdn/Kconfig | 4 ---- drivers/isdn/icn/Kconfig | 4 ---- drivers/isdn/pcbit/Kconfig | 4 ---- drivers/isdn/sc/Kconfig | 4 ---- 6 files changed, 24 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/act2000/Kconfig b/drivers/isdn/act2000/Kconfig index 3fc1a5434ef7..fa2673fc69c2 100644 --- a/drivers/isdn/act2000/Kconfig +++ b/drivers/isdn/act2000/Kconfig @@ -1,6 +1,3 @@ -# -# Config.in for IBM Active 2000 ISDN driver -# config ISDN_DRV_ACT2000 tristate "IBM Active 2000 support" depends on ISA @@ -10,4 +7,3 @@ config ISDN_DRV_ACT2000 into the card using a utility which is part of the latest isdn4k-utils package. Please read the file for more information. - diff --git a/drivers/isdn/capi/Kconfig b/drivers/isdn/capi/Kconfig index e1afd60924fb..b2a04755c96a 100644 --- a/drivers/isdn/capi/Kconfig +++ b/drivers/isdn/capi/Kconfig @@ -1,6 +1,3 @@ -# -# Config.in for the CAPI subsystem -# config ISDN_DRV_AVMB1_VERBOSE_REASON bool "Verbose reason code reporting" default y @@ -59,4 +56,3 @@ config ISDN_CAPI_CAPIDRV the legacy isdn4linux link layer. If you have a card which is supported by a CAPI driver, but still want to use old features like ippp interfaces or ttyI emulation, say Y/M here. - diff --git a/drivers/isdn/hysdn/Kconfig b/drivers/isdn/hysdn/Kconfig index c9e4231968ef..e86bc6583d71 100644 --- a/drivers/isdn/hysdn/Kconfig +++ b/drivers/isdn/hysdn/Kconfig @@ -1,6 +1,3 @@ -# -# Config.in for HYSDN ISDN driver -# config HYSDN tristate "Hypercope HYSDN cards (Champ, Ergo, Metro) support (module only)" depends on m && PROC_FS && PCI @@ -15,4 +12,3 @@ config HYSDN_CAPI depends on HYSDN && ISDN_CAPI help Say Y here if you like to use Hypercope's CAPI 2.0 interface. - diff --git a/drivers/isdn/icn/Kconfig b/drivers/isdn/icn/Kconfig index 89d15eed765e..4534f21a1852 100644 --- a/drivers/isdn/icn/Kconfig +++ b/drivers/isdn/icn/Kconfig @@ -1,6 +1,3 @@ -# -# Config.in for ICN ISDN driver -# config ISDN_DRV_ICN tristate "ICN 2B and 4B support" depends on ISA @@ -13,4 +10,3 @@ config ISDN_DRV_ICN separately. See and for more information. - diff --git a/drivers/isdn/pcbit/Kconfig b/drivers/isdn/pcbit/Kconfig index ffba6eca1244..e9b2dd85d410 100644 --- a/drivers/isdn/pcbit/Kconfig +++ b/drivers/isdn/pcbit/Kconfig @@ -1,6 +1,3 @@ -# -# Config.in for PCBIT ISDN driver -# config ISDN_DRV_PCBIT tristate "PCBIT-D support" depends on ISA && (BROKEN || X86) @@ -11,4 +8,3 @@ config ISDN_DRV_PCBIT the card using a utility which is distributed separately. See and for more information. - diff --git a/drivers/isdn/sc/Kconfig b/drivers/isdn/sc/Kconfig index e6510ca7bf43..7469863a7925 100644 --- a/drivers/isdn/sc/Kconfig +++ b/drivers/isdn/sc/Kconfig @@ -1,6 +1,3 @@ -# -# Config.in for Spellcaster ISDN driver -# config ISDN_DRV_SC tristate "Spellcaster support" depends on ISA @@ -9,4 +6,3 @@ config ISDN_DRV_SC driver currently builds only in a modularized version. To build it, choose M here: the module will be called sc. See for more information. - -- cgit v1.2.2 From 4a9b5e5053a184ada2e9b19aee12b6200bb8980f Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 10 Nov 2009 20:30:37 -0800 Subject: speedfax: declare MODULE_FIRMWARE Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/speedfax.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/isdn') diff --git a/drivers/isdn/hardware/mISDN/speedfax.c b/drivers/isdn/hardware/mISDN/speedfax.c index ff3a4e290da3..7726afdbb40b 100644 --- a/drivers/isdn/hardware/mISDN/speedfax.c +++ b/drivers/isdn/hardware/mISDN/speedfax.c @@ -110,6 +110,7 @@ set_debug(const char *val, struct kernel_param *kp) MODULE_AUTHOR("Karsten Keil"); MODULE_LICENSE("GPL v2"); MODULE_VERSION(SPEEDFAX_REV); +MODULE_FIRMWARE("isdn/ISAR.BIN"); module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Speedfax debug mask"); module_param(irqloops, uint, S_IRUGO | S_IWUSR); -- cgit v1.2.2 From 5452fee23eddb5ebb46f13aba50c8930c160e1da Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 19 Nov 2009 09:55:53 +0000 Subject: drivers/isdn/gigaset: tasklet_init - Remove unnecessary leading & from second arg Changed function pointer use from non-majority address-of style to majority short form without & via: grep -rPl "\btasklet_init\s*\([^,\)]+,\s*\&" drivers/isdn | while read file ; do \ perl -i -e 'local $/; while (<>) { s@(\btasklet_init\s*\([^,\)]+,\s*)\&@\1@g ; print ; }' $file ;\ done Compile tested allyesconfig x86 Signed-off-by: Joe Perches drivers/isdn/gigaset/bas-gigaset.c | 4 ++-- drivers/isdn/gigaset/common.c | 2 +- drivers/isdn/gigaset/interface.c | 2 +- drivers/isdn/gigaset/ser-gigaset.c | 2 +- drivers/isdn/gigaset/usb-gigaset.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) Signed-off-by: David S. Miller --- drivers/isdn/gigaset/bas-gigaset.c | 4 ++-- drivers/isdn/gigaset/common.c | 2 +- drivers/isdn/gigaset/interface.c | 2 +- drivers/isdn/gigaset/ser-gigaset.c | 2 +- drivers/isdn/gigaset/usb-gigaset.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 9fd19db045fb..95ebc5129895 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -2117,7 +2117,7 @@ static int gigaset_initbcshw(struct bc_state *bcs) return 0; } tasklet_init(&ubc->sent_tasklet, - &write_iso_tasklet, (unsigned long) bcs); + write_iso_tasklet, (unsigned long) bcs); spin_lock_init(&ubc->isoinlock); for (i = 0; i < BAS_INURBS; ++i) @@ -2138,7 +2138,7 @@ static int gigaset_initbcshw(struct bc_state *bcs) ubc->shared0s = 0; ubc->stolen0s = 0; tasklet_init(&ubc->rcvd_tasklet, - &read_iso_tasklet, (unsigned long) bcs); + read_iso_tasklet, (unsigned long) bcs); return 1; } diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index c438cfcb7c6d..82ed1cd14ff5 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -727,7 +727,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, cs->ev_tail = 0; cs->ev_head = 0; - tasklet_init(&cs->event_tasklet, &gigaset_handle_event, + tasklet_init(&cs->event_tasklet, gigaset_handle_event, (unsigned long) cs); cs->commands_pending = 0; cs->cur_at_seq = 0; diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index 577809c03aed..d2260b0055fc 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -584,7 +584,7 @@ void gigaset_if_init(struct cardstate *cs) if (!drv->have_tty) return; - tasklet_init(&cs->if_wake_tasklet, &if_wake, (unsigned long) cs); + tasklet_init(&cs->if_wake_tasklet, if_wake, (unsigned long) cs); mutex_lock(&cs->mutex); cs->tty_dev = tty_register_device(drv->tty, cs->minor_index, NULL); diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index ac3409ea5d99..168d585d64d8 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c @@ -434,7 +434,7 @@ static int gigaset_initcshw(struct cardstate *cs) dev_set_drvdata(&cs->hw.ser->dev.dev, cs); tasklet_init(&cs->write_tasklet, - &gigaset_modem_fill, (unsigned long) cs); + gigaset_modem_fill, (unsigned long) cs); return 1; } diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index f56b2a83793e..3ab1daeb276b 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c @@ -614,7 +614,7 @@ static int gigaset_initcshw(struct cardstate *cs) ucs->bulk_out_urb = NULL; ucs->read_urb = NULL; tasklet_init(&cs->write_tasklet, - &gigaset_modem_fill, (unsigned long) cs); + gigaset_modem_fill, (unsigned long) cs); return 1; } -- cgit v1.2.2 From 868575d1e87ff2091800aea816972ddb46de60d5 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 13 Dec 2006 19:46:43 +0900 Subject: pcmcia: Pass struct pcmcia_device to pcmcia_map_mem_page() No logic changes, just pass struct pcmcia_device to pcmcia_map_mem_page() [linux@dominikbrodowski.net: update to 2.6.31] CC: netdev@vger.kernel.org CC: linux-wireless@vger.kernel.org CC: linux-scsi@vger.kernel.org CC: Jiri Kosina Acked-by: Karsten Keil (for ISDN) Signed-off-by: Magnus Damm Signed-off-by: Dominik Brodowski --- drivers/isdn/hisax/sedlbauer_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index 33d7530527c7..598e17a551b7 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -276,7 +276,7 @@ static int sedlbauer_config_check(struct pcmcia_device *p_dev, return -ENODEV; map.Page = 0; map.CardOffset = mem->win[0].card_addr; - if (pcmcia_map_mem_page(p_dev->win, &map) != 0) + if (pcmcia_map_mem_page(p_dev, p_dev->win, &map) != 0) return -ENODEV; } return 0; -- cgit v1.2.2 From 6838b03fc6564ea07d0cd87ea6e198d90ab1fc3e Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 3 Nov 2009 01:31:52 +0100 Subject: pcmcia: pcmcia_request_window() doesn't need a pointer to a pointer pcmcia_request_window() only needs a pointer to struct pcmcia_device, not a pointer to a pointer. CC: netdev@vger.kernel.org CC: linux-wireless@vger.kernel.org CC: linux-scsi@vger.kernel.org CC: Jiri Kosina Acked-by: Karsten Keil (for ISDN) Signed-off-by: Dominik Brodowski --- drivers/isdn/hisax/sedlbauer_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index 598e17a551b7..331716fc6b30 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -272,7 +272,7 @@ static int sedlbauer_config_check(struct pcmcia_device *p_dev, req->Base = mem->win[0].host_addr; req->Size = mem->win[0].len; req->AccessSpeed = 0; - if (pcmcia_request_window(&p_dev, req, &p_dev->win) != 0) + if (pcmcia_request_window(p_dev, req, &p_dev->win) != 0) return -ENODEV; map.Page = 0; map.CardOffset = mem->win[0].card_addr; -- cgit v1.2.2 From 5fa9167a1bf5f5a4b7282f5e7ac56a4a5a1fa044 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 8 Nov 2009 17:24:46 +0100 Subject: pcmcia: rework the irq_req_t typedef Most of the irq_req_t typedef'd struct can be re-worked quite easily: (1) IRQInfo2 was unused in any case, so drop it. (2) IRQInfo1 was used write-only, so drop it. (3) Instance (private data to be passed to the IRQ handler): Most PCMCIA drivers using pcmcia_request_irq() to actually register an IRQ handler set the "dev_id" to the same pointer as the "priv" pointer in struct pcmcia_device. Modify the two exceptions (ipwireless, ibmtr_cs) to also work this waym and set the IRQ handler's "dev_id" to p_dev->priv unconditionally. (4) Handler is to be of type irq_handler_t. (5) Handler != NULL already tells whether an IRQ handler is present. Therefore, we do not need the IRQ_HANDLER_PRESENT flag in irq_req_t.Attributes. CC: netdev@vger.kernel.org CC: linux-bluetooth@vger.kernel.org CC: linux-ide@vger.kernel.org CC: linux-wireless@vger.kernel.org CC: linux-scsi@vger.kernel.org CC: alsa-devel@alsa-project.org CC: Jaroslav Kysela CC: Jiri Kosina CC: Karsten Keil for the Bluetooth parts: Acked-by: Marcel Holtmann Signed-off-by: Dominik Brodowski --- drivers/isdn/hardware/avm/avm_cs.c | 2 -- drivers/isdn/hisax/avma1_cs.c | 2 -- drivers/isdn/hisax/elsa_cs.c | 1 - drivers/isdn/hisax/sedlbauer_cs.c | 1 - drivers/isdn/hisax/teles_cs.c | 1 - 5 files changed, 7 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index d388eadb9fdb..5a6ae646a636 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c @@ -111,8 +111,6 @@ static int avmcs_probe(struct pcmcia_device *p_dev) p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; - p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; - /* General socket configuration */ p_dev->conf.Attributes = CONF_ENABLE_IRQ; p_dev->conf.IntType = INT_MEMORY_AND_IO; diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index 6d963f9a09ce..f9bdff39cf4a 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c @@ -123,8 +123,6 @@ static int avma1cs_probe(struct pcmcia_device *p_dev) p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; - p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; - /* General socket configuration */ p_dev->conf.Attributes = CONF_ENABLE_IRQ; p_dev->conf.IntType = INT_MEMORY_AND_IO; diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index cdcd2979fcd4..a2f709f53974 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -138,7 +138,6 @@ static int elsa_cs_probe(struct pcmcia_device *link) /* Interrupt setup */ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; - link->irq.IRQInfo1 = IRQ_LEVEL_ID|IRQ_SHARE_ID; link->irq.Handler = NULL; /* diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index 331716fc6b30..af5d393cc2d0 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -145,7 +145,6 @@ static int sedlbauer_probe(struct pcmcia_device *link) /* Interrupt setup */ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; - link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = NULL; /* diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index 7b11c15b3a97..ea705394ce2b 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c @@ -128,7 +128,6 @@ static int teles_probe(struct pcmcia_device *link) /* Interrupt setup */ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; - link->irq.IRQInfo1 = IRQ_LEVEL_ID|IRQ_SHARE_ID; link->irq.Handler = NULL; /* -- cgit v1.2.2 From af901ca181d92aac3a7dc265144a9081a86d8f39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Goddard=20Rosa?= Date: Sat, 14 Nov 2009 13:09:05 -0200 Subject: tree-wide: fix assorted typos all over the place MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That is "success", "unknown", "through", "performance", "[re|un]mapping" , "access", "default", "reasonable", "[con]currently", "temperature" , "channel", "[un]used", "application", "example","hierarchy", "therefore" , "[over|under]flow", "contiguous", "threshold", "enough" and others. Signed-off-by: André Goddard Rosa Signed-off-by: Jiri Kosina --- drivers/isdn/capi/capidrv.c | 2 +- drivers/isdn/hardware/eicon/di.c | 2 +- drivers/isdn/hardware/eicon/maintidi.c | 4 ++-- drivers/isdn/hardware/mISDN/hfcsusb.c | 2 +- drivers/isdn/hardware/mISDN/hfcsusb.h | 2 +- drivers/isdn/hardware/mISDN/mISDNisar.c | 2 +- drivers/isdn/hisax/hfc_usb.c | 2 +- drivers/isdn/i4l/isdn_ppp.c | 6 +++--- drivers/isdn/i4l/isdn_ttyfax.c | 2 +- drivers/isdn/mISDN/dsp_core.c | 2 +- drivers/isdn/mISDN/tei.c | 2 +- 11 files changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c index 3e6d17f42a98..66b7d7a86474 100644 --- a/drivers/isdn/capi/capidrv.c +++ b/drivers/isdn/capi/capidrv.c @@ -830,7 +830,7 @@ static void handle_controller(_cmsg * cmsg) case 0: break; case 1: s = "unknown class"; break; case 2: s = "unknown function"; break; - default: s = "unkown error"; break; + default: s = "unknown error"; break; } if (s) printk(KERN_INFO "capidrv-%d: %s from controller 0x%x function %d: %s\n", diff --git a/drivers/isdn/hardware/eicon/di.c b/drivers/isdn/hardware/eicon/di.c index b029d130eb21..cb14ae3e7154 100644 --- a/drivers/isdn/hardware/eicon/di.c +++ b/drivers/isdn/hardware/eicon/di.c @@ -806,7 +806,7 @@ static void xdi_xlog_request (byte Adapter, byte Id, DELIVERY - indication entered isdn_rc function RNR=... - application had returned RNR=... after the look ahead callback - RNum=0 - aplication had not returned any buffer to copy + RNum=0 - application had not returned any buffer to copy this indication and will copy it self COMPLETE - XDI had copied the data to the buffers provided bu the application and is about to issue the diff --git a/drivers/isdn/hardware/eicon/maintidi.c b/drivers/isdn/hardware/eicon/maintidi.c index 23960cb6eaab..e7cfb3b5647f 100644 --- a/drivers/isdn/hardware/eicon/maintidi.c +++ b/drivers/isdn/hardware/eicon/maintidi.c @@ -385,7 +385,7 @@ static int SuperTraceMessageInput (void* hLib) { } break; default: - diva_mnt_internal_dprintf (0, DLI_ERR, "Unknon IDI Ind (DMA mode): %02x", Ind); + diva_mnt_internal_dprintf (0, DLI_ERR, "Unknown IDI Ind (DMA mode): %02x", Ind); } p += (this_ind_length+1); total_length -= (4 + this_ind_length); @@ -420,7 +420,7 @@ static int SuperTraceMessageInput (void* hLib) { } break; default: - diva_mnt_internal_dprintf (0, DLI_ERR, "Unknon IDI Ind: %02x", Ind); + diva_mnt_internal_dprintf (0, DLI_ERR, "Unknown IDI Ind: %02x", Ind); } } } diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c index fc46a26cb14f..a64bb6c67ba7 100644 --- a/drivers/isdn/hardware/mISDN/hfcsusb.c +++ b/drivers/isdn/hardware/mISDN/hfcsusb.c @@ -721,7 +721,7 @@ hfcsusb_setup_bch(struct bchannel *bch, int protocol) switch (protocol) { case (-1): /* used for init */ bch->state = -1; - /* fall trough */ + /* fall through */ case (ISDN_P_NONE): if (bch->state == ISDN_P_NONE) return 0; /* already in idle state */ diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.h b/drivers/isdn/hardware/mISDN/hfcsusb.h index 43efe7358fa3..369196adae03 100644 --- a/drivers/isdn/hardware/mISDN/hfcsusb.h +++ b/drivers/isdn/hardware/mISDN/hfcsusb.h @@ -150,7 +150,7 @@ symbolic(struct hfcusb_symbolic_list list[], const int num) for (i = 0; list[i].name != NULL; i++) if (list[i].num == num) return list[i].name; - return ""; + return ""; } /* USB descriptor need to contain one of the following EndPoint combination: */ diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c index de352a17673a..09095c747110 100644 --- a/drivers/isdn/hardware/mISDN/mISDNisar.c +++ b/drivers/isdn/hardware/mISDN/mISDNisar.c @@ -860,7 +860,7 @@ isar_pump_statev_modem(struct isar_ch *ch, u8 devt) { pr_debug("%s: pump stev GSTN CLEAR\n", ch->is->name); break; default: - pr_info("u%s: nknown pump stev %x\n", ch->is->name, devt); + pr_info("u%s: unknown pump stev %x\n", ch->is->name, devt); break; } } diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c index 9de54202c90c..ad5831f37d84 100644 --- a/drivers/isdn/hisax/hfc_usb.c +++ b/drivers/isdn/hisax/hfc_usb.c @@ -1086,7 +1086,7 @@ hfc_usb_l2l1(struct hisax_if *my_hisax_if, int pr, void *arg) break; default: DBG(HFCUSB_DBG_STATES, - "HFC_USB: hfc_usb_d_l2l1: unkown state : %#x", pr); + "HFC_USB: hfc_usb_d_l2l1: unknown state : %#x", pr); break; } } diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c index 2d14b64202a3..0f4ea7d16a15 100644 --- a/drivers/isdn/i4l/isdn_ppp.c +++ b/drivers/isdn/i4l/isdn_ppp.c @@ -836,7 +836,7 @@ isdn_ppp_write(int min, struct file *file, const char __user *buf, int count) unsigned short hl; struct sk_buff *skb; /* - * we need to reserve enought space in front of + * we need to reserve enough space in front of * sk_buff. old call to dev_alloc_skb only reserved * 16 bytes, now we are looking what the driver want */ @@ -1326,7 +1326,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev) struct sk_buff *new_skb; unsigned short hl; /* - * we need to reserve enought space in front of + * we need to reserve enough space in front of * sk_buff. old call to dev_alloc_skb only reserved * 16 bytes, now we are looking what the driver want. */ @@ -1685,7 +1685,7 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, * * try to accomplish several tasks: * - reassemble any complete fragment sequence (non-null 'start' - * indicates there is a continguous sequence present) + * indicates there is a contiguous sequence present) * - discard any incomplete sequences that are below minseq -- due * to the fact that sender always increment sequence number, if there * is an incomplete sequence below minseq, no new fragments would diff --git a/drivers/isdn/i4l/isdn_ttyfax.c b/drivers/isdn/i4l/isdn_ttyfax.c index 78f7660c1d0e..4c41f191d4e2 100644 --- a/drivers/isdn/i4l/isdn_ttyfax.c +++ b/drivers/isdn/i4l/isdn_ttyfax.c @@ -470,7 +470,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info) } return 0; } - /* BADMUL=value - dummy 0=disable errorchk disabled (treshold multiplier) */ + /* BADMUL=value - dummy 0=disable errorchk disabled (threshold multiplier) */ if (!strncmp(p[0], "BADMUL", 6)) { p[0] += 6; switch (*p[0]) { diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c index 77ee2867c8b4..43ff4d3b046e 100644 --- a/drivers/isdn/mISDN/dsp_core.c +++ b/drivers/isdn/mISDN/dsp_core.c @@ -110,7 +110,7 @@ * crossconnections and conferences via software if not possible through * hardware. If hardware capability is available, hardware is used. * - * Echo: Is generated by CMX and is used to check performane of hard and + * Echo: Is generated by CMX and is used to check performance of hard and * software CMX. * * The CMX has special functions for conferences with one, two and more diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c index e04bad6c5baf..6d4da6095885 100644 --- a/drivers/isdn/mISDN/tei.c +++ b/drivers/isdn/mISDN/tei.c @@ -725,7 +725,7 @@ tei_id_ver_tout_net(struct FsmInst *fi, int event, void *arg) if (tm->rcnt == 1) { if (*debug & DEBUG_L2_TEI) tm->tei_m.printdebug(fi, - "check req for tei %d sucessful\n", tm->l2->tei); + "check req for tei %d successful\n", tm->l2->tei); mISDN_FsmChangeState(fi, ST_TEI_NOP); } else if (tm->rcnt > 1) { /* duplicate assignment; remove */ -- cgit v1.2.2 From e15c1c1f3f903f679c9782b540f9d52c80c99610 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sat, 28 Nov 2009 18:12:06 +0100 Subject: pcmcia: remove unused IRQ_FIRST_SHARED Komuro pointed out that IRQ_FIRST_SHARED is not used at all in the PCMCIA subsystem, so remove it. Also, remove two bogus assignments. CC: Karsten Keil CC: netdev@vger.kernel.org CC: alsa-devel@alsa-project.org CC: Komuro Signed-off-by: Dominik Brodowski --- drivers/isdn/hardware/avm/avm_cs.c | 3 +-- drivers/isdn/hisax/avma1_cs.c | 3 +-- drivers/isdn/hisax/elsa_cs.c | 2 +- drivers/isdn/hisax/sedlbauer_cs.c | 2 +- drivers/isdn/hisax/teles_cs.c | 2 +- 5 files changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index 5a6ae646a636..94b796d84053 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c @@ -108,8 +108,7 @@ static int avmcs_probe(struct pcmcia_device *p_dev) p_dev->io.NumPorts2 = 0; /* Interrupt setup */ - p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; - p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; /* General socket configuration */ p_dev->conf.Attributes = CONF_ENABLE_IRQ; diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index f9bdff39cf4a..e5deb15cf40c 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c @@ -120,8 +120,7 @@ static int avma1cs_probe(struct pcmcia_device *p_dev) p_dev->io.IOAddrLines = 5; /* Interrupt setup */ - p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; - p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; /* General socket configuration */ p_dev->conf.Attributes = CONF_ENABLE_IRQ; diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index a2f709f53974..c9a30b1c9237 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -137,7 +137,7 @@ static int elsa_cs_probe(struct pcmcia_device *link) local->cardnr = -1; /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; link->irq.Handler = NULL; /* diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index af5d393cc2d0..7836ec3c7f86 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -144,7 +144,7 @@ static int sedlbauer_probe(struct pcmcia_device *link) link->priv = local; /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; link->irq.Handler = NULL; /* diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index ea705394ce2b..b0c5976cbdb3 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c @@ -127,7 +127,7 @@ static int teles_probe(struct pcmcia_device *link) link->priv = local; /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; link->irq.Handler = NULL; /* -- cgit v1.2.2 From 073886ff23bfbe7b88c9133d7a556d6ec51f0b50 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sat, 5 Dec 2009 08:04:16 +0000 Subject: gigaset: don't enable any debugging output by default When built with debugging support, the Gigaset driver enabled some debugging messages by default. Change the default to "all off". Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 82ed1cd14ff5..664b0c519c3e 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -29,7 +29,7 @@ #endif /* Module parameters */ -int gigaset_debuglevel = DEBUG_DEFAULT; +int gigaset_debuglevel; EXPORT_SYMBOL_GPL(gigaset_debuglevel); module_param_named(debug, gigaset_debuglevel, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(debug, "debug level"); -- cgit v1.2.2 From 01a1e7ec6c3769dc7c5fde23ebc253c6be5f68eb Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Fri, 18 Dec 2009 20:30:11 -0800 Subject: mISDN: use DECLARE_COMPLETION_ONSTACK for non-constant completion The _ONSTACK variant should be used for on-stack completion, otherwise it will break lockdep. Signed-off-by: Yong Zhang Acked-by: Karsten Keil Signed-off-by: David S. Miller --- drivers/isdn/mISDN/l1oip_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c index 7e5f30dbc0a0..f1e8af54dff0 100644 --- a/drivers/isdn/mISDN/l1oip_core.c +++ b/drivers/isdn/mISDN/l1oip_core.c @@ -661,7 +661,7 @@ l1oip_socket_thread(void *data) size_t recvbuf_size = 1500; int recvlen; struct socket *socket = NULL; - DECLARE_COMPLETION(wait); + DECLARE_COMPLETION_ONSTACK(wait); /* allocate buffer memory */ recvbuf = kmalloc(recvbuf_size, GFP_KERNEL); -- cgit v1.2.2 From 073bd90f03d98bc3168865f21573c9b232777c13 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 21 Dec 2009 14:25:32 +0000 Subject: drivers/isdn: eliminate duplicated test The code checked slot_rx twice. Check slot_tx by analogy with the bank case. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression E; @@ ( *E && E | *E || E ) // Signed-off-by: Julia Lawall Cc: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/hfcmulti.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index a6624ad252c5..1a1420d7a828 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c @@ -3152,7 +3152,7 @@ static void hfcmulti_pcm(struct hfc_multi *hc, int ch, int slot_tx, int bank_tx, int slot_rx, int bank_rx) { - if (slot_rx < 0 || slot_rx < 0 || bank_tx < 0 || bank_rx < 0) { + if (slot_tx < 0 || slot_rx < 0 || bank_tx < 0 || bank_rx < 0) { /* disable PCM */ mode_hfcmulti(hc, ch, hc->chan[ch].protocol, -1, 0, -1, 0); return; -- cgit v1.2.2 From 9a58a80a701bdb2d220cdab4914218df5b48d781 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 14 Jan 2010 03:10:54 -0800 Subject: proc_fops: convert drivers/isdn/ to seq_file Convert code away from ->read_proc/->write_proc interfaces. Switch to proc_create()/proc_create_data() which make addition of proc entries reliable wrt NULL ->proc_fops, NULL ->data and so on. Problem with ->read_proc et al is described here commit 786d7e1612f0b0adb6046f19b906609e4fe8b1ba "Fix rmmod/read/write races in /proc entries" [akpm@linux-foundation.org: CONFIG_PROC_FS=n build fix] Signed-off-by: Alexey Dobriyan Signed-off-by: Tilman Schmidt Signed-off-by: Karsten Keil Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 99 ++++++---------- drivers/isdn/capi/capidrv.c | 55 +++------ drivers/isdn/capi/kcapi.c | 8 +- drivers/isdn/gigaset/capi.c | 75 ++++++------ drivers/isdn/hardware/avm/avmcard.h | 6 +- drivers/isdn/hardware/avm/b1.c | 54 +++++---- drivers/isdn/hardware/avm/b1dma.c | 71 ++++++------ drivers/isdn/hardware/avm/b1isa.c | 2 +- drivers/isdn/hardware/avm/b1pci.c | 4 +- drivers/isdn/hardware/avm/b1pcmcia.c | 2 +- drivers/isdn/hardware/avm/c4.c | 53 +++++---- drivers/isdn/hardware/avm/t1isa.c | 2 +- drivers/isdn/hardware/avm/t1pci.c | 2 +- drivers/isdn/hardware/eicon/capimain.c | 40 ++++--- drivers/isdn/hardware/eicon/diva_didd.c | 45 ++++---- drivers/isdn/hardware/eicon/divasi.c | 48 ++++---- drivers/isdn/hardware/eicon/divasproc.c | 198 ++++++++++++++------------------ drivers/isdn/hysdn/hycapi.c | 56 ++++----- 18 files changed, 384 insertions(+), 436 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 65bf91e16a42..79f9364aded6 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -33,6 +33,7 @@ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ #include #include +#include #include #include #include @@ -1407,114 +1408,84 @@ static void capinc_tty_exit(void) * /proc/capi/capi20: * minor applid nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt */ -static int proc_capidev_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int capi20_proc_show(struct seq_file *m, void *v) { struct capidev *cdev; struct list_head *l; - int len = 0; read_lock(&capidev_list_lock); list_for_each(l, &capidev_list) { cdev = list_entry(l, struct capidev, list); - len += sprintf(page+len, "0 %d %lu %lu %lu %lu\n", + seq_printf(m, "0 %d %lu %lu %lu %lu\n", cdev->ap.applid, cdev->ap.nrecvctlpkt, cdev->ap.nrecvdatapkt, cdev->ap.nsentctlpkt, cdev->ap.nsentdatapkt); - if (len <= off) { - off -= len; - len = 0; - } else { - if (len-off > count) - goto endloop; - } } - -endloop: read_unlock(&capidev_list_lock); - if (len < count) - *eof = 1; - if (len > count) len = count; - if (len < 0) len = 0; - return len; + return 0; } +static int capi20_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, capi20_proc_show, NULL); +} + +static const struct file_operations capi20_proc_fops = { + .owner = THIS_MODULE, + .open = capi20_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + /* * /proc/capi/capi20ncci: * applid ncci */ -static int proc_capincci_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int capi20ncci_proc_show(struct seq_file *m, void *v) { struct capidev *cdev; struct capincci *np; struct list_head *l; - int len = 0; read_lock(&capidev_list_lock); list_for_each(l, &capidev_list) { cdev = list_entry(l, struct capidev, list); for (np=cdev->nccis; np; np = np->next) { - len += sprintf(page+len, "%d 0x%x\n", + seq_printf(m, "%d 0x%x\n", cdev->ap.applid, np->ncci); - if (len <= off) { - off -= len; - len = 0; - } else { - if (len-off > count) - goto endloop; - } } } -endloop: read_unlock(&capidev_list_lock); - *start = page+off; - if (len < count) - *eof = 1; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return 0; } -static struct procfsentries { - char *name; - mode_t mode; - int (*read_proc)(char *page, char **start, off_t off, - int count, int *eof, void *data); - struct proc_dir_entry *procent; -} procfsentries[] = { - /* { "capi", S_IFDIR, 0 }, */ - { "capi/capi20", 0 , proc_capidev_read_proc }, - { "capi/capi20ncci", 0 , proc_capincci_read_proc }, +static int capi20ncci_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, capi20ncci_proc_show, NULL); +} + +static const struct file_operations capi20ncci_proc_fops = { + .owner = THIS_MODULE, + .open = capi20ncci_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, }; static void __init proc_init(void) { - int nelem = ARRAY_SIZE(procfsentries); - int i; - - for (i=0; i < nelem; i++) { - struct procfsentries *p = procfsentries + i; - p->procent = create_proc_entry(p->name, p->mode, NULL); - if (p->procent) p->procent->read_proc = p->read_proc; - } + proc_create("capi/capi20", 0, NULL, &capi20_proc_fops); + proc_create("capi/capi20ncci", 0, NULL, &capi20ncci_proc_fops); } static void __exit proc_exit(void) { - int nelem = ARRAY_SIZE(procfsentries); - int i; - - for (i=nelem-1; i >= 0; i--) { - struct procfsentries *p = procfsentries + i; - if (p->procent) { - remove_proc_entry(p->name, NULL); - p->procent = NULL; - } - } + remove_proc_entry("capi/capi20", NULL); + remove_proc_entry("capi/capi20ncci", NULL); } /* -------- init function and module interface ---------------------- */ diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c index 66b7d7a86474..bb450152fb74 100644 --- a/drivers/isdn/capi/capidrv.c +++ b/drivers/isdn/capi/capidrv.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -2229,59 +2230,37 @@ static void lower_callback(unsigned int cmd, u32 contr, void *data) * /proc/capi/capidrv: * nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt */ -static int proc_capidrv_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int capidrv_proc_show(struct seq_file *m, void *v) { - int len = 0; - - len += sprintf(page+len, "%lu %lu %lu %lu\n", + seq_printf(m, "%lu %lu %lu %lu\n", global.ap.nrecvctlpkt, global.ap.nrecvdatapkt, global.ap.nsentctlpkt, global.ap.nsentdatapkt); - if (off+count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len-off) ? count : len-off); + return 0; +} + +static int capidrv_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, capidrv_proc_show, NULL); } -static struct procfsentries { - char *name; - mode_t mode; - int (*read_proc)(char *page, char **start, off_t off, - int count, int *eof, void *data); - struct proc_dir_entry *procent; -} procfsentries[] = { - /* { "capi", S_IFDIR, 0 }, */ - { "capi/capidrv", 0 , proc_capidrv_read_proc }, +static const struct file_operations capidrv_proc_fops = { + .owner = THIS_MODULE, + .open = capidrv_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, }; static void __init proc_init(void) { - int nelem = ARRAY_SIZE(procfsentries); - int i; - - for (i=0; i < nelem; i++) { - struct procfsentries *p = procfsentries + i; - p->procent = create_proc_entry(p->name, p->mode, NULL); - if (p->procent) p->procent->read_proc = p->read_proc; - } + proc_create("capi/capidrv", 0, NULL, &capidrv_proc_fops); } static void __exit proc_exit(void) { - int nelem = ARRAY_SIZE(procfsentries); - int i; - - for (i=nelem-1; i >= 0; i--) { - struct procfsentries *p = procfsentries + i; - if (p->procent) { - remove_proc_entry(p->name, NULL); - p->procent = NULL; - } - } + remove_proc_entry("capi/capidrv", NULL); } static int __init capidrv_init(void) diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index dc506ab99cac..b0bacf377c18 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -490,13 +490,7 @@ attach_capi_ctr(struct capi_ctr *card) card->traceflag = showcapimsgs; sprintf(card->procfn, "capi/controllers/%d", card->cnr); - card->procent = create_proc_entry(card->procfn, 0, NULL); - if (card->procent) { - card->procent->read_proc = - (int (*)(char *,char **,off_t,int,int *,void *)) - card->ctr_read_proc; - card->procent->data = card; - } + card->procent = proc_create_data(card->procfn, 0, NULL, card->proc_fops, card); ncards++; printk(KERN_NOTICE "kcapi: Controller [%03d]: %s attached\n", diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index 3f5cd06af104..6f0ae32906bf 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -13,6 +13,8 @@ #include "gigaset.h" #include +#include +#include #include #include #include @@ -2106,35 +2108,22 @@ static char *gigaset_procinfo(struct capi_ctr *ctr) return ctr->name; /* ToDo: more? */ } -/** - * gigaset_ctr_read_proc() - build controller proc file entry - * @page: buffer of PAGE_SIZE bytes for receiving the entry. - * @start: unused. - * @off: unused. - * @count: unused. - * @eof: unused. - * @ctr: controller descriptor structure. - * - * Return value: length of generated entry - */ -static int gigaset_ctr_read_proc(char *page, char **start, off_t off, - int count, int *eof, struct capi_ctr *ctr) +static int gigaset_proc_show(struct seq_file *m, void *v) { + struct capi_ctr *ctr = m->private; struct cardstate *cs = ctr->driverdata; char *s; int i; - int len = 0; - len += sprintf(page+len, "%-16s %s\n", "name", ctr->name); - len += sprintf(page+len, "%-16s %s %s\n", "dev", + + seq_printf(m, "%-16s %s\n", "name", ctr->name); + seq_printf(m, "%-16s %s %s\n", "dev", dev_driver_string(cs->dev), dev_name(cs->dev)); - len += sprintf(page+len, "%-16s %d\n", "id", cs->myid); + seq_printf(m, "%-16s %d\n", "id", cs->myid); if (cs->gotfwver) - len += sprintf(page+len, "%-16s %d.%d.%d.%d\n", "firmware", + seq_printf(m, "%-16s %d.%d.%d.%d\n", "firmware", cs->fwver[0], cs->fwver[1], cs->fwver[2], cs->fwver[3]); - len += sprintf(page+len, "%-16s %d\n", "channels", - cs->channels); - len += sprintf(page+len, "%-16s %s\n", "onechannel", - cs->onechannel ? "yes" : "no"); + seq_printf(m, "%-16s %d\n", "channels", cs->channels); + seq_printf(m, "%-16s %s\n", "onechannel", cs->onechannel ? "yes" : "no"); switch (cs->mode) { case M_UNKNOWN: @@ -2152,7 +2141,7 @@ static int gigaset_ctr_read_proc(char *page, char **start, off_t off, default: s = "??"; } - len += sprintf(page+len, "%-16s %s\n", "mode", s); + seq_printf(m, "%-16s %s\n", "mode", s); switch (cs->mstate) { case MS_UNINITIALIZED: @@ -2176,25 +2165,21 @@ static int gigaset_ctr_read_proc(char *page, char **start, off_t off, default: s = "??"; } - len += sprintf(page+len, "%-16s %s\n", "mstate", s); + seq_printf(m, "%-16s %s\n", "mstate", s); - len += sprintf(page+len, "%-16s %s\n", "running", - cs->running ? "yes" : "no"); - len += sprintf(page+len, "%-16s %s\n", "connected", - cs->connected ? "yes" : "no"); - len += sprintf(page+len, "%-16s %s\n", "isdn_up", - cs->isdn_up ? "yes" : "no"); - len += sprintf(page+len, "%-16s %s\n", "cidmode", - cs->cidmode ? "yes" : "no"); + seq_printf(m, "%-16s %s\n", "running", cs->running ? "yes" : "no"); + seq_printf(m, "%-16s %s\n", "connected", cs->connected ? "yes" : "no"); + seq_printf(m, "%-16s %s\n", "isdn_up", cs->isdn_up ? "yes" : "no"); + seq_printf(m, "%-16s %s\n", "cidmode", cs->cidmode ? "yes" : "no"); for (i = 0; i < cs->channels; i++) { - len += sprintf(page+len, "[%d]%-13s %d\n", i, "corrupted", + seq_printf(m, "[%d]%-13s %d\n", i, "corrupted", cs->bcs[i].corrupted); - len += sprintf(page+len, "[%d]%-13s %d\n", i, "trans_down", + seq_printf(m, "[%d]%-13s %d\n", i, "trans_down", cs->bcs[i].trans_down); - len += sprintf(page+len, "[%d]%-13s %d\n", i, "trans_up", + seq_printf(m, "[%d]%-13s %d\n", i, "trans_up", cs->bcs[i].trans_up); - len += sprintf(page+len, "[%d]%-13s %d\n", i, "chstate", + seq_printf(m, "[%d]%-13s %d\n", i, "chstate", cs->bcs[i].chstate); switch (cs->bcs[i].proto2) { case L2_BITSYNC: @@ -2209,11 +2194,23 @@ static int gigaset_ctr_read_proc(char *page, char **start, off_t off, default: s = "??"; } - len += sprintf(page+len, "[%d]%-13s %s\n", i, "proto2", s); + seq_printf(m, "[%d]%-13s %s\n", i, "proto2", s); } - return len; + return 0; } +static int gigaset_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, gigaset_proc_show, PDE(inode)->data); +} + +static const struct file_operations gigaset_proc_fops = { + .owner = THIS_MODULE, + .open = gigaset_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; static struct capi_driver capi_driver_gigaset = { .name = "gigaset", @@ -2256,7 +2253,7 @@ int gigaset_isdn_register(struct cardstate *cs, const char *isdnid) iif->ctr.release_appl = gigaset_release_appl; iif->ctr.send_message = gigaset_send_message; iif->ctr.procinfo = gigaset_procinfo; - iif->ctr.ctr_read_proc = gigaset_ctr_read_proc; + iif->ctr.proc_fops = &gigaset_proc_fops; INIT_LIST_HEAD(&iif->appls); skb_queue_head_init(&iif->sendqueue); atomic_set(&iif->sendqlen, 0); diff --git a/drivers/isdn/hardware/avm/avmcard.h b/drivers/isdn/hardware/avm/avmcard.h index d964f07e4a56..a70e8854461d 100644 --- a/drivers/isdn/hardware/avm/avmcard.h +++ b/drivers/isdn/hardware/avm/avmcard.h @@ -556,8 +556,7 @@ u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); void b1_parse_version(avmctrl_info *card); irqreturn_t b1_interrupt(int interrupt, void *devptr); -int b1ctl_read_proc(char *page, char **start, off_t off, - int count, int *eof, struct capi_ctr *ctrl); +extern const struct file_operations b1ctl_proc_fops; avmcard_dmainfo *avmcard_dma_alloc(char *name, struct pci_dev *, long rsize, long ssize); @@ -577,7 +576,6 @@ void b1dma_register_appl(struct capi_ctr *ctrl, capi_register_params *rp); void b1dma_release_appl(struct capi_ctr *ctrl, u16 appl); u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); -int b1dmactl_read_proc(char *page, char **start, off_t off, - int count, int *eof, struct capi_ctr *ctrl); +extern const struct file_operations b1dmactl_proc_fops; #endif /* _AVMCARD_H_ */ diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c index a7c0083e78a7..c38fa0f4c729 100644 --- a/drivers/isdn/hardware/avm/b1.c +++ b/drivers/isdn/hardware/avm/b1.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include #include @@ -634,18 +636,17 @@ irqreturn_t b1_interrupt(int interrupt, void *devptr) } /* ------------------------------------------------------------- */ -int b1ctl_read_proc(char *page, char **start, off_t off, - int count, int *eof, struct capi_ctr *ctrl) +static int b1ctl_proc_show(struct seq_file *m, void *v) { + struct capi_ctr *ctrl = m->private; avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmcard *card = cinfo->card; u8 flag; - int len = 0; char *s; - len += sprintf(page+len, "%-16s %s\n", "name", card->name); - len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port); - len += sprintf(page+len, "%-16s %d\n", "irq", card->irq); + seq_printf(m, "%-16s %s\n", "name", card->name); + seq_printf(m, "%-16s 0x%x\n", "io", card->port); + seq_printf(m, "%-16s %d\n", "irq", card->irq); switch (card->cardtype) { case avm_b1isa: s = "B1 ISA"; break; case avm_b1pci: s = "B1 PCI"; break; @@ -658,20 +659,20 @@ int b1ctl_read_proc(char *page, char **start, off_t off, case avm_c2: s = "C2"; break; default: s = "???"; break; } - len += sprintf(page+len, "%-16s %s\n", "type", s); + seq_printf(m, "%-16s %s\n", "type", s); if (card->cardtype == avm_t1isa) - len += sprintf(page+len, "%-16s %d\n", "cardnr", card->cardnr); + seq_printf(m, "%-16s %d\n", "cardnr", card->cardnr); if ((s = cinfo->version[VER_DRIVER]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_driver", s); + seq_printf(m, "%-16s %s\n", "ver_driver", s); if ((s = cinfo->version[VER_CARDTYPE]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s); + seq_printf(m, "%-16s %s\n", "ver_cardtype", s); if ((s = cinfo->version[VER_SERIAL]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_serial", s); + seq_printf(m, "%-16s %s\n", "ver_serial", s); if (card->cardtype != avm_m1) { flag = ((u8 *)(ctrl->profile.manu))[3]; if (flag) - len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n", + seq_printf(m, "%-16s%s%s%s%s%s%s%s\n", "protocol", (flag & 0x01) ? " DSS1" : "", (flag & 0x02) ? " CT1" : "", @@ -685,7 +686,7 @@ int b1ctl_read_proc(char *page, char **start, off_t off, if (card->cardtype != avm_m1) { flag = ((u8 *)(ctrl->profile.manu))[5]; if (flag) - len += sprintf(page+len, "%-16s%s%s%s%s\n", + seq_printf(m, "%-16s%s%s%s%s\n", "linetype", (flag & 0x01) ? " point to point" : "", (flag & 0x02) ? " point to multipoint" : "", @@ -693,16 +694,25 @@ int b1ctl_read_proc(char *page, char **start, off_t off, (flag & 0x04) ? " leased line with D-channel" : "" ); } - len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); - - if (off+count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len-off) ? count : len-off); + seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname); + + return 0; +} + +static int b1ctl_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, b1ctl_proc_show, PDE(inode)->data); } +const struct file_operations b1ctl_proc_fops = { + .owner = THIS_MODULE, + .open = b1ctl_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +EXPORT_SYMBOL(b1ctl_proc_fops); + /* ------------------------------------------------------------- */ #ifdef CONFIG_PCI @@ -781,8 +791,6 @@ EXPORT_SYMBOL(b1_send_message); EXPORT_SYMBOL(b1_parse_version); EXPORT_SYMBOL(b1_interrupt); -EXPORT_SYMBOL(b1ctl_read_proc); - static int __init b1_init(void) { char *p; diff --git a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c index 0e84aaae43fd..124550d0dbf3 100644 --- a/drivers/isdn/hardware/avm/b1dma.c +++ b/drivers/isdn/hardware/avm/b1dma.c @@ -11,6 +11,8 @@ #include #include +#include +#include #include #include #include @@ -855,21 +857,20 @@ u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) /* ------------------------------------------------------------- */ -int b1dmactl_read_proc(char *page, char **start, off_t off, - int count, int *eof, struct capi_ctr *ctrl) +static int b1dmactl_proc_show(struct seq_file *m, void *v) { + struct capi_ctr *ctrl = m->private; avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmcard *card = cinfo->card; u8 flag; - int len = 0; char *s; u32 txoff, txlen, rxoff, rxlen, csr; unsigned long flags; - len += sprintf(page+len, "%-16s %s\n", "name", card->name); - len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port); - len += sprintf(page+len, "%-16s %d\n", "irq", card->irq); - len += sprintf(page+len, "%-16s 0x%lx\n", "membase", card->membase); + seq_printf(m, "%-16s %s\n", "name", card->name); + seq_printf(m, "%-16s 0x%x\n", "io", card->port); + seq_printf(m, "%-16s %d\n", "irq", card->irq); + seq_printf(m, "%-16s 0x%lx\n", "membase", card->membase); switch (card->cardtype) { case avm_b1isa: s = "B1 ISA"; break; case avm_b1pci: s = "B1 PCI"; break; @@ -882,18 +883,18 @@ int b1dmactl_read_proc(char *page, char **start, off_t off, case avm_c2: s = "C2"; break; default: s = "???"; break; } - len += sprintf(page+len, "%-16s %s\n", "type", s); + seq_printf(m, "%-16s %s\n", "type", s); if ((s = cinfo->version[VER_DRIVER]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_driver", s); + seq_printf(m, "%-16s %s\n", "ver_driver", s); if ((s = cinfo->version[VER_CARDTYPE]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s); + seq_printf(m, "%-16s %s\n", "ver_cardtype", s); if ((s = cinfo->version[VER_SERIAL]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_serial", s); + seq_printf(m, "%-16s %s\n", "ver_serial", s); if (card->cardtype != avm_m1) { flag = ((u8 *)(ctrl->profile.manu))[3]; if (flag) - len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n", + seq_printf(m, "%-16s%s%s%s%s%s%s%s\n", "protocol", (flag & 0x01) ? " DSS1" : "", (flag & 0x02) ? " CT1" : "", @@ -907,7 +908,7 @@ int b1dmactl_read_proc(char *page, char **start, off_t off, if (card->cardtype != avm_m1) { flag = ((u8 *)(ctrl->profile.manu))[5]; if (flag) - len += sprintf(page+len, "%-16s%s%s%s%s\n", + seq_printf(m, "%-16s%s%s%s%s\n", "linetype", (flag & 0x01) ? " point to point" : "", (flag & 0x02) ? " point to multipoint" : "", @@ -915,7 +916,7 @@ int b1dmactl_read_proc(char *page, char **start, off_t off, (flag & 0x04) ? " leased line with D-channel" : "" ); } - len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); + seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname); spin_lock_irqsave(&card->lock, flags); @@ -930,27 +931,30 @@ int b1dmactl_read_proc(char *page, char **start, off_t off, spin_unlock_irqrestore(&card->lock, flags); - len += sprintf(page+len, "%-16s 0x%lx\n", - "csr (cached)", (unsigned long)card->csr); - len += sprintf(page+len, "%-16s 0x%lx\n", - "csr", (unsigned long)csr); - len += sprintf(page+len, "%-16s %lu\n", - "txoff", (unsigned long)txoff); - len += sprintf(page+len, "%-16s %lu\n", - "txlen", (unsigned long)txlen); - len += sprintf(page+len, "%-16s %lu\n", - "rxoff", (unsigned long)rxoff); - len += sprintf(page+len, "%-16s %lu\n", - "rxlen", (unsigned long)rxlen); - - if (off+count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len-off) ? count : len-off); + seq_printf(m, "%-16s 0x%lx\n", "csr (cached)", (unsigned long)card->csr); + seq_printf(m, "%-16s 0x%lx\n", "csr", (unsigned long)csr); + seq_printf(m, "%-16s %lu\n", "txoff", (unsigned long)txoff); + seq_printf(m, "%-16s %lu\n", "txlen", (unsigned long)txlen); + seq_printf(m, "%-16s %lu\n", "rxoff", (unsigned long)rxoff); + seq_printf(m, "%-16s %lu\n", "rxlen", (unsigned long)rxlen); + + return 0; +} + +static int b1dmactl_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, b1dmactl_proc_show, PDE(inode)->data); } +const struct file_operations b1dmactl_proc_fops = { + .owner = THIS_MODULE, + .open = b1dmactl_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +EXPORT_SYMBOL(b1dmactl_proc_fops); + /* ------------------------------------------------------------- */ EXPORT_SYMBOL(b1dma_reset); @@ -963,7 +967,6 @@ EXPORT_SYMBOL(b1dma_reset_ctr); EXPORT_SYMBOL(b1dma_register_appl); EXPORT_SYMBOL(b1dma_release_appl); EXPORT_SYMBOL(b1dma_send_message); -EXPORT_SYMBOL(b1dmactl_read_proc); static int __init b1dma_init(void) { diff --git a/drivers/isdn/hardware/avm/b1isa.c b/drivers/isdn/hardware/avm/b1isa.c index 6461a32bc838..ff5390546f92 100644 --- a/drivers/isdn/hardware/avm/b1isa.c +++ b/drivers/isdn/hardware/avm/b1isa.c @@ -121,7 +121,7 @@ static int b1isa_probe(struct pci_dev *pdev) cinfo->capi_ctrl.load_firmware = b1_load_firmware; cinfo->capi_ctrl.reset_ctr = b1_reset_ctr; cinfo->capi_ctrl.procinfo = b1isa_procinfo; - cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc; + cinfo->capi_ctrl.proc_fops = &b1ctl_proc_fops; strcpy(cinfo->capi_ctrl.name, card->name); retval = attach_capi_ctr(&cinfo->capi_ctrl); diff --git a/drivers/isdn/hardware/avm/b1pci.c b/drivers/isdn/hardware/avm/b1pci.c index 5b314a2c4049..c97e4315079d 100644 --- a/drivers/isdn/hardware/avm/b1pci.c +++ b/drivers/isdn/hardware/avm/b1pci.c @@ -112,7 +112,7 @@ static int b1pci_probe(struct capicardparams *p, struct pci_dev *pdev) cinfo->capi_ctrl.load_firmware = b1_load_firmware; cinfo->capi_ctrl.reset_ctr = b1_reset_ctr; cinfo->capi_ctrl.procinfo = b1pci_procinfo; - cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc; + cinfo->capi_ctrl.proc_fops = &b1ctl_proc_fops; strcpy(cinfo->capi_ctrl.name, card->name); cinfo->capi_ctrl.owner = THIS_MODULE; @@ -251,7 +251,7 @@ static int b1pciv4_probe(struct capicardparams *p, struct pci_dev *pdev) cinfo->capi_ctrl.load_firmware = b1dma_load_firmware; cinfo->capi_ctrl.reset_ctr = b1dma_reset_ctr; cinfo->capi_ctrl.procinfo = b1pciv4_procinfo; - cinfo->capi_ctrl.ctr_read_proc = b1dmactl_read_proc; + cinfo->capi_ctrl.proc_fops = &b1dmactl_proc_fops; strcpy(cinfo->capi_ctrl.name, card->name); retval = attach_capi_ctr(&cinfo->capi_ctrl); diff --git a/drivers/isdn/hardware/avm/b1pcmcia.c b/drivers/isdn/hardware/avm/b1pcmcia.c index 7740403b40e1..d6391e0afeea 100644 --- a/drivers/isdn/hardware/avm/b1pcmcia.c +++ b/drivers/isdn/hardware/avm/b1pcmcia.c @@ -108,7 +108,7 @@ static int b1pcmcia_add_card(unsigned int port, unsigned irq, cinfo->capi_ctrl.load_firmware = b1_load_firmware; cinfo->capi_ctrl.reset_ctr = b1_reset_ctr; cinfo->capi_ctrl.procinfo = b1pcmcia_procinfo; - cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc; + cinfo->capi_ctrl.proc_fops = &b1ctl_proc_fops; strcpy(cinfo->capi_ctrl.name, card->name); retval = attach_capi_ctr(&cinfo->capi_ctrl); diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c index 6833301a45fc..de6e6b311819 100644 --- a/drivers/isdn/hardware/avm/c4.c +++ b/drivers/isdn/hardware/avm/c4.c @@ -11,6 +11,8 @@ #include #include +#include +#include #include #include #include @@ -1062,19 +1064,18 @@ static char *c4_procinfo(struct capi_ctr *ctrl) return cinfo->infobuf; } -static int c4_read_proc(char *page, char **start, off_t off, - int count, int *eof, struct capi_ctr *ctrl) +static int c4_proc_show(struct seq_file *m, void *v) { + struct capi_ctr *ctrl = m->private; avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmcard *card = cinfo->card; u8 flag; - int len = 0; char *s; - len += sprintf(page+len, "%-16s %s\n", "name", card->name); - len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port); - len += sprintf(page+len, "%-16s %d\n", "irq", card->irq); - len += sprintf(page+len, "%-16s 0x%lx\n", "membase", card->membase); + seq_printf(m, "%-16s %s\n", "name", card->name); + seq_printf(m, "%-16s 0x%x\n", "io", card->port); + seq_printf(m, "%-16s %d\n", "irq", card->irq); + seq_printf(m, "%-16s 0x%lx\n", "membase", card->membase); switch (card->cardtype) { case avm_b1isa: s = "B1 ISA"; break; case avm_b1pci: s = "B1 PCI"; break; @@ -1087,18 +1088,18 @@ static int c4_read_proc(char *page, char **start, off_t off, case avm_c2: s = "C2"; break; default: s = "???"; break; } - len += sprintf(page+len, "%-16s %s\n", "type", s); + seq_printf(m, "%-16s %s\n", "type", s); if ((s = cinfo->version[VER_DRIVER]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_driver", s); + seq_printf(m, "%-16s %s\n", "ver_driver", s); if ((s = cinfo->version[VER_CARDTYPE]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s); + seq_printf(m, "%-16s %s\n", "ver_cardtype", s); if ((s = cinfo->version[VER_SERIAL]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_serial", s); + seq_printf(m, "%-16s %s\n", "ver_serial", s); if (card->cardtype != avm_m1) { flag = ((u8 *)(ctrl->profile.manu))[3]; if (flag) - len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n", + seq_printf(m, "%-16s%s%s%s%s%s%s%s\n", "protocol", (flag & 0x01) ? " DSS1" : "", (flag & 0x02) ? " CT1" : "", @@ -1112,7 +1113,7 @@ static int c4_read_proc(char *page, char **start, off_t off, if (card->cardtype != avm_m1) { flag = ((u8 *)(ctrl->profile.manu))[5]; if (flag) - len += sprintf(page+len, "%-16s%s%s%s%s\n", + seq_printf(m, "%-16s%s%s%s%s\n", "linetype", (flag & 0x01) ? " point to point" : "", (flag & 0x02) ? " point to multipoint" : "", @@ -1120,16 +1121,24 @@ static int c4_read_proc(char *page, char **start, off_t off, (flag & 0x04) ? " leased line with D-channel" : "" ); } - len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); - - if (off+count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len-off) ? count : len-off); + seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname); + + return 0; } +static int c4_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, c4_proc_show, PDE(inode)->data); +} + +static const struct file_operations c4_proc_fops = { + .owner = THIS_MODULE, + .open = c4_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + /* ------------------------------------------------------------- */ static int c4_add_card(struct capicardparams *p, struct pci_dev *dev, @@ -1201,7 +1210,7 @@ static int c4_add_card(struct capicardparams *p, struct pci_dev *dev, cinfo->capi_ctrl.load_firmware = c4_load_firmware; cinfo->capi_ctrl.reset_ctr = c4_reset_ctr; cinfo->capi_ctrl.procinfo = c4_procinfo; - cinfo->capi_ctrl.ctr_read_proc = c4_read_proc; + cinfo->capi_ctrl.proc_fops = &c4_proc_fops; strcpy(cinfo->capi_ctrl.name, card->name); retval = attach_capi_ctr(&cinfo->capi_ctrl); diff --git a/drivers/isdn/hardware/avm/t1isa.c b/drivers/isdn/hardware/avm/t1isa.c index 1c53fd49adb6..baeeb3c2a3ee 100644 --- a/drivers/isdn/hardware/avm/t1isa.c +++ b/drivers/isdn/hardware/avm/t1isa.c @@ -429,7 +429,7 @@ static int t1isa_probe(struct pci_dev *pdev, int cardnr) cinfo->capi_ctrl.load_firmware = t1isa_load_firmware; cinfo->capi_ctrl.reset_ctr = t1isa_reset_ctr; cinfo->capi_ctrl.procinfo = t1isa_procinfo; - cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc; + cinfo->capi_ctrl.proc_fops = &b1ctl_proc_fops; strcpy(cinfo->capi_ctrl.name, card->name); retval = attach_capi_ctr(&cinfo->capi_ctrl); diff --git a/drivers/isdn/hardware/avm/t1pci.c b/drivers/isdn/hardware/avm/t1pci.c index e6d298d75146..5a3f83098018 100644 --- a/drivers/isdn/hardware/avm/t1pci.c +++ b/drivers/isdn/hardware/avm/t1pci.c @@ -119,7 +119,7 @@ static int t1pci_add_card(struct capicardparams *p, struct pci_dev *pdev) cinfo->capi_ctrl.load_firmware = b1dma_load_firmware; cinfo->capi_ctrl.reset_ctr = b1dma_reset_ctr; cinfo->capi_ctrl.procinfo = t1pci_procinfo; - cinfo->capi_ctrl.ctr_read_proc = b1dmactl_read_proc; + cinfo->capi_ctrl.proc_fops = &b1dmactl_proc_fops; strcpy(cinfo->capi_ctrl.name, card->name); retval = attach_capi_ctr(&cinfo->capi_ctrl); diff --git a/drivers/isdn/hardware/eicon/capimain.c b/drivers/isdn/hardware/eicon/capimain.c index 98fcdfc7ca55..0f073cd73763 100644 --- a/drivers/isdn/hardware/eicon/capimain.c +++ b/drivers/isdn/hardware/eicon/capimain.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "os_capi.h" @@ -75,25 +76,32 @@ void diva_os_free_message_buffer(diva_os_message_buffer_s * dmb) /* * proc function for controller info */ -static int diva_ctl_read_proc(char *page, char **start, off_t off, - int count, int *eof, struct capi_ctr *ctrl) +static int diva_ctl_proc_show(struct seq_file *m, void *v) { + struct capi_ctr *ctrl = m->private; diva_card *card = (diva_card *) ctrl->driverdata; - int len = 0; - - len += sprintf(page + len, "%s\n", ctrl->name); - len += sprintf(page + len, "Serial No. : %s\n", ctrl->serial); - len += sprintf(page + len, "Id : %d\n", card->Id); - len += sprintf(page + len, "Channels : %d\n", card->d.channels); - - if (off + count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len - off) ? count : len - off); + + seq_printf(m, "%s\n", ctrl->name); + seq_printf(m, "Serial No. : %s\n", ctrl->serial); + seq_printf(m, "Id : %d\n", card->Id); + seq_printf(m, "Channels : %d\n", card->d.channels); + + return 0; +} + +static int diva_ctl_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, diva_ctl_proc_show, NULL); } +static const struct file_operations diva_ctl_proc_fops = { + .owner = THIS_MODULE, + .open = diva_ctl_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + /* * set additional os settings in capi_ctr struct */ @@ -102,7 +110,7 @@ void diva_os_set_controller_struct(struct capi_ctr *ctrl) ctrl->driver_name = DRIVERLNAME; ctrl->load_firmware = NULL; ctrl->reset_ctr = NULL; - ctrl->ctr_read_proc = diva_ctl_read_proc; + ctrl->proc_fops = &diva_ctl_proc_fops; ctrl->owner = THIS_MODULE; } diff --git a/drivers/isdn/hardware/eicon/diva_didd.c b/drivers/isdn/hardware/eicon/diva_didd.c index 993b14cf1778..5d06a7437824 100644 --- a/drivers/isdn/hardware/eicon/diva_didd.c +++ b/drivers/isdn/hardware/eicon/diva_didd.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "platform.h" @@ -62,39 +63,41 @@ static char *getrev(const char *revision) return rev; } -static int -proc_read(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int divadidd_proc_show(struct seq_file *m, void *v) { - int len = 0; char tmprev[32]; strcpy(tmprev, main_revision); - len += sprintf(page + len, "%s\n", DRIVERNAME); - len += sprintf(page + len, "name : %s\n", DRIVERLNAME); - len += sprintf(page + len, "release : %s\n", DRIVERRELEASE_DIDD); - len += sprintf(page + len, "build : %s(%s)\n", + seq_printf(m, "%s\n", DRIVERNAME); + seq_printf(m, "name : %s\n", DRIVERLNAME); + seq_printf(m, "release : %s\n", DRIVERRELEASE_DIDD); + seq_printf(m, "build : %s(%s)\n", diva_didd_common_code_build, DIVA_BUILD); - len += sprintf(page + len, "revision : %s\n", getrev(tmprev)); - - if (off + count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len - off) ? count : len - off); + seq_printf(m, "revision : %s\n", getrev(tmprev)); + + return 0; } +static int divadidd_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, divadidd_proc_show, NULL); +} + +static const struct file_operations divadidd_proc_fops = { + .owner = THIS_MODULE, + .open = divadidd_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static int DIVA_INIT_FUNCTION create_proc(void) { proc_net_eicon = proc_mkdir("eicon", init_net.proc_net); if (proc_net_eicon) { - if ((proc_didd = - create_proc_entry(DRIVERLNAME, S_IFREG | S_IRUGO, - proc_net_eicon))) { - proc_didd->read_proc = proc_read; - } + proc_didd = proc_create(DRIVERLNAME, S_IRUGO, proc_net_eicon, + &divadidd_proc_fops); return (1); } return (0); diff --git a/drivers/isdn/hardware/eicon/divasi.c b/drivers/isdn/hardware/eicon/divasi.c index 69e71ebe7841..f577719ab3fa 100644 --- a/drivers/isdn/hardware/eicon/divasi.c +++ b/drivers/isdn/hardware/eicon/divasi.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -86,39 +87,40 @@ static void diva_um_timer_function(unsigned long data); extern struct proc_dir_entry *proc_net_eicon; static struct proc_dir_entry *um_idi_proc_entry = NULL; -static int -um_idi_proc_read(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int um_idi_proc_show(struct seq_file *m, void *v) { - int len = 0; char tmprev[32]; - len += sprintf(page + len, "%s\n", DRIVERNAME); - len += sprintf(page + len, "name : %s\n", DRIVERLNAME); - len += sprintf(page + len, "release : %s\n", DRIVERRELEASE_IDI); + seq_printf(m, "%s\n", DRIVERNAME); + seq_printf(m, "name : %s\n", DRIVERLNAME); + seq_printf(m, "release : %s\n", DRIVERRELEASE_IDI); strcpy(tmprev, main_revision); - len += sprintf(page + len, "revision : %s\n", getrev(tmprev)); - len += sprintf(page + len, "build : %s\n", DIVA_BUILD); - len += sprintf(page + len, "major : %d\n", major); - - if (off + count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len - off) ? count : len - off); + seq_printf(m, "revision : %s\n", getrev(tmprev)); + seq_printf(m, "build : %s\n", DIVA_BUILD); + seq_printf(m, "major : %d\n", major); + + return 0; +} + +static int um_idi_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, um_idi_proc_show, NULL); } +static const struct file_operations um_idi_proc_fops = { + .owner = THIS_MODULE, + .open = um_idi_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static int DIVA_INIT_FUNCTION create_um_idi_proc(void) { - um_idi_proc_entry = create_proc_entry(DRIVERLNAME, - S_IFREG | S_IRUGO | S_IWUSR, - proc_net_eicon); + um_idi_proc_entry = proc_create(DRIVERLNAME, S_IRUGO, proc_net_eicon, + &um_idi_proc_fops); if (!um_idi_proc_entry) return (0); - - um_idi_proc_entry->read_proc = um_idi_proc_read; - return (1); } diff --git a/drivers/isdn/hardware/eicon/divasproc.c b/drivers/isdn/hardware/eicon/divasproc.c index 040827288ec9..46d44a942624 100644 --- a/drivers/isdn/hardware/eicon/divasproc.c +++ b/drivers/isdn/hardware/eicon/divasproc.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -141,14 +142,10 @@ void remove_divas_proc(void) } } -/* -** write group_optimization -*/ -static int -write_grp_opt(struct file *file, const char __user *buffer, unsigned long count, - void *data) +static ssize_t grp_opt_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { - diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data; + diva_os_xdi_adapter_t *a = PDE(file->f_path.dentry->d_inode)->data; PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; if ((count == 1) || (count == 2)) { @@ -172,14 +169,10 @@ write_grp_opt(struct file *file, const char __user *buffer, unsigned long count, return (-EINVAL); } -/* -** write dynamic_l1_down -*/ -static int -write_d_l1_down(struct file *file, const char __user *buffer, unsigned long count, - void *data) +static ssize_t d_l1_down_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { - diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data; + diva_os_xdi_adapter_t *a = PDE(file->f_path.dentry->d_inode)->data; PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; if ((count == 1) || (count == 2)) { @@ -203,63 +196,62 @@ write_d_l1_down(struct file *file, const char __user *buffer, unsigned long coun return (-EINVAL); } - -/* -** read dynamic_l1_down -*/ -static int -read_d_l1_down(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int d_l1_down_proc_show(struct seq_file *m, void *v) { - int len = 0; - diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data; + diva_os_xdi_adapter_t *a = m->private; PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; - len += sprintf(page + len, "%s\n", + seq_printf(m, "%s\n", (IoAdapter->capi_cfg. cfg_1 & DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON) ? "1" : "0"); + return 0; +} - if (off + count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len - off) ? count : len - off); +static int d_l1_down_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, d_l1_down_proc_show, PDE(inode)->data); } -/* -** read group_optimization -*/ -static int -read_grp_opt(char *page, char **start, off_t off, int count, int *eof, - void *data) +static const struct file_operations d_l1_down_proc_fops = { + .owner = THIS_MODULE, + .open = d_l1_down_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = d_l1_down_proc_write, +}; + +static int grp_opt_proc_show(struct seq_file *m, void *v) { - int len = 0; - diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data; + diva_os_xdi_adapter_t *a = m->private; PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; - len += sprintf(page + len, "%s\n", + seq_printf(m, "%s\n", (IoAdapter->capi_cfg. cfg_1 & DIVA_XDI_CAPI_CFG_1_GROUP_POPTIMIZATION_ON) ? "1" : "0"); + return 0; +} - if (off + count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len - off) ? count : len - off); +static int grp_opt_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, grp_opt_proc_show, PDE(inode)->data); } -/* -** info write -*/ -static int -info_write(struct file *file, const char __user *buffer, unsigned long count, - void *data) +static const struct file_operations grp_opt_proc_fops = { + .owner = THIS_MODULE, + .open = grp_opt_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = grp_opt_proc_write, +}; + +static ssize_t info_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { - diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data; + diva_os_xdi_adapter_t *a = PDE(file->f_path.dentry->d_inode)->data; PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; char c[4]; @@ -277,63 +269,46 @@ info_write(struct file *file, const char __user *buffer, unsigned long count, return (-EINVAL); } -/* -** info read -*/ -static int -info_read(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int info_proc_show(struct seq_file *m, void *v) { int i = 0; - int len = 0; char *p; char tmpser[16]; - diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data; + diva_os_xdi_adapter_t *a = m->private; PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; - len += - sprintf(page + len, "Name : %s\n", - IoAdapter->Properties.Name); - len += sprintf(page + len, "DSP state : %08x\n", a->dsp_mask); - len += sprintf(page + len, "Channels : %02d\n", - IoAdapter->Properties.Channels); - len += sprintf(page + len, "E. max/used : %03d/%03d\n", + seq_printf(m, "Name : %s\n", IoAdapter->Properties.Name); + seq_printf(m, "DSP state : %08x\n", a->dsp_mask); + seq_printf(m, "Channels : %02d\n", IoAdapter->Properties.Channels); + seq_printf(m, "E. max/used : %03d/%03d\n", IoAdapter->e_max, IoAdapter->e_count); diva_get_vserial_number(IoAdapter, tmpser); - len += sprintf(page + len, "Serial : %s\n", tmpser); - len += - sprintf(page + len, "IRQ : %d\n", - IoAdapter->irq_info.irq_nr); - len += sprintf(page + len, "CardIndex : %d\n", a->CardIndex); - len += sprintf(page + len, "CardOrdinal : %d\n", a->CardOrdinal); - len += sprintf(page + len, "Controller : %d\n", a->controller); - len += sprintf(page + len, "Bus-Type : %s\n", + seq_printf(m, "Serial : %s\n", tmpser); + seq_printf(m, "IRQ : %d\n", IoAdapter->irq_info.irq_nr); + seq_printf(m, "CardIndex : %d\n", a->CardIndex); + seq_printf(m, "CardOrdinal : %d\n", a->CardOrdinal); + seq_printf(m, "Controller : %d\n", a->controller); + seq_printf(m, "Bus-Type : %s\n", (a->Bus == DIVAS_XDI_ADAPTER_BUS_ISA) ? "ISA" : "PCI"); - len += sprintf(page + len, "Port-Name : %s\n", a->port_name); + seq_printf(m, "Port-Name : %s\n", a->port_name); if (a->Bus == DIVAS_XDI_ADAPTER_BUS_PCI) { - len += - sprintf(page + len, "PCI-bus : %d\n", - a->resources.pci.bus); - len += - sprintf(page + len, "PCI-func : %d\n", - a->resources.pci.func); + seq_printf(m, "PCI-bus : %d\n", a->resources.pci.bus); + seq_printf(m, "PCI-func : %d\n", a->resources.pci.func); for (i = 0; i < 8; i++) { if (a->resources.pci.bar[i]) { - len += - sprintf(page + len, + seq_printf(m, "Mem / I/O %d : 0x%x / mapped : 0x%lx", i, a->resources.pci.bar[i], (unsigned long) a->resources. pci.addr[i]); if (a->resources.pci.length[i]) { - len += - sprintf(page + len, + seq_printf(m, " / length : %d", a->resources.pci. length[i]); } - len += sprintf(page + len, "\n"); + seq_putc(m, '\n'); } } } @@ -353,16 +328,25 @@ info_read(char *page, char **start, off_t off, int count, int *eof, } else { p = "ready"; } - len += sprintf(page + len, "State : %s\n", p); + seq_printf(m, "State : %s\n", p); - if (off + count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len - off) ? count : len - off); + return 0; +} + +static int info_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, info_proc_show, PDE(inode)->data); } +static const struct file_operations info_proc_fops = { + .owner = THIS_MODULE, + .open = info_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = info_proc_write, +}; + /* ** adapter proc init/de-init */ @@ -380,28 +364,20 @@ int create_adapter_proc(diva_os_xdi_adapter_t * a) return (0); a->proc_adapter_dir = (void *) de; - if (!(pe = - create_proc_entry(info_proc_name, S_IFREG | S_IRUGO | S_IWUSR, de))) + pe = proc_create_data(info_proc_name, S_IRUGO | S_IWUSR, de, + &info_proc_fops, a); + if (!pe) return (0); a->proc_info = (void *) pe; - pe->write_proc = info_write; - pe->read_proc = info_read; - pe->data = a; - if ((pe = create_proc_entry(grp_opt_proc_name, - S_IFREG | S_IRUGO | S_IWUSR, de))) { + pe = proc_create_data(grp_opt_proc_name, S_IRUGO | S_IWUSR, de, + &grp_opt_proc_fops, a); + if (pe) a->proc_grp_opt = (void *) pe; - pe->write_proc = write_grp_opt; - pe->read_proc = read_grp_opt; - pe->data = a; - } - if ((pe = create_proc_entry(d_l1_down_proc_name, - S_IFREG | S_IRUGO | S_IWUSR, de))) { + pe = proc_create_data(d_l1_down_proc_name, S_IRUGO | S_IWUSR, de, + &d_l1_down_proc_fops, a); + if (pe) a->proc_d_l1_down = (void *) pe; - pe->write_proc = write_d_l1_down; - pe->read_proc = read_d_l1_down; - pe->data = a; - } DBG_TRC(("proc entry %s created", tmp)); diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c index 4ffaa14b9fc4..fe874afa4f81 100644 --- a/drivers/isdn/hysdn/hycapi.c +++ b/drivers/isdn/hysdn/hycapi.c @@ -11,6 +11,8 @@ */ #include +#include +#include #include #include #include @@ -432,26 +434,16 @@ static u16 hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) return retval; } -/********************************************************************* -hycapi_read_proc - -Informations provided in the /proc/capi-entries. - -*********************************************************************/ - -static int hycapi_read_proc(char *page, char **start, off_t off, - int count, int *eof, struct capi_ctr *ctrl) +static int hycapi_proc_show(struct seq_file *m, void *v) { + struct capi_ctr *ctrl = m->private; hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); hysdn_card *card = cinfo->card; - int len = 0; char *s; -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "hycapi_read_proc\n"); -#endif - len += sprintf(page+len, "%-16s %s\n", "name", cinfo->cardname); - len += sprintf(page+len, "%-16s 0x%x\n", "io", card->iobase); - len += sprintf(page+len, "%-16s %d\n", "irq", card->irq); + + seq_printf(m, "%-16s %s\n", "name", cinfo->cardname); + seq_printf(m, "%-16s 0x%x\n", "io", card->iobase); + seq_printf(m, "%-16s %d\n", "irq", card->irq); switch (card->brdtype) { case BD_PCCARD: s = "HYSDN Hycard"; break; @@ -461,24 +453,32 @@ static int hycapi_read_proc(char *page, char **start, off_t off, case BD_PLEXUS: s = "HYSDN Plexus30"; break; default: s = "???"; break; } - len += sprintf(page+len, "%-16s %s\n", "type", s); + seq_printf(m, "%-16s %s\n", "type", s); if ((s = cinfo->version[VER_DRIVER]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_driver", s); + seq_printf(m, "%-16s %s\n", "ver_driver", s); if ((s = cinfo->version[VER_CARDTYPE]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s); + seq_printf(m, "%-16s %s\n", "ver_cardtype", s); if ((s = cinfo->version[VER_SERIAL]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_serial", s); + seq_printf(m, "%-16s %s\n", "ver_serial", s); - len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); + seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname); - if (off+count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len-off) ? count : len-off); + return 0; +} + +static int hycapi_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, hycapi_proc_show, PDE(inode)->data); } +static const struct file_operations hycapi_proc_fops = { + .owner = THIS_MODULE, + .open = hycapi_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + /************************************************************** hycapi_load_firmware @@ -774,7 +774,7 @@ hycapi_capi_create(hysdn_card *card) ctrl->load_firmware = hycapi_load_firmware; ctrl->reset_ctr = hycapi_reset_ctr; ctrl->procinfo = hycapi_procinfo; - ctrl->ctr_read_proc = hycapi_read_proc; + ctrl->proc_fops = &hycapi_proc_fops; strcpy(ctrl->name, cinfo->cardname); ctrl->owner = THIS_MODULE; -- cgit v1.2.2 From e23e11792a77c7d54f363841cd5e33074fb0c8c9 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 2 Feb 2010 12:43:44 +0000 Subject: hisax: timeout off by one in waitrecmsg() With `while (timeout++ < maxdelay)' timeout reaches maxdelay + 1 after the loop This is probably unlikely a problem in practice. Signed-off-by: Roel Kluin Cc: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/isdn/hisax/isar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c index bfeb9b6aa043..6bde16c00fb5 100644 --- a/drivers/isdn/hisax/isar.c +++ b/drivers/isdn/hisax/isar.c @@ -138,7 +138,7 @@ waitrecmsg(struct IsdnCardState *cs, u_char *len, while((!(cs->BC_Read_Reg(cs, 0, ISAR_IRQBIT) & ISAR_IRQSTA)) && (timeout++ < maxdelay)) udelay(1); - if (timeout >= maxdelay) { + if (timeout > maxdelay) { printk(KERN_WARNING"isar recmsg IRQSTA timeout\n"); return(0); } -- cgit v1.2.2 From f0f4d641d4ebfeb4194e9c26dfa6286802e2e8d1 Mon Sep 17 00:00:00 2001 From: Darren Jenkins Date: Tue, 2 Feb 2010 12:43:45 +0000 Subject: hardware/mISDN/mISDNinfineon.c: bail out of loop on error If setup_instance() fails we kfree() the card, and then use it in the next loop iteration. So lets bail out of the loop instead. Coverity CID: 13357 Signed-off-by: Darren Jenkins Cc: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/mISDNinfineon.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/isdn') diff --git a/drivers/isdn/hardware/mISDN/mISDNinfineon.c b/drivers/isdn/hardware/mISDN/mISDNinfineon.c index 62441ba53b95..36c6c616a655 100644 --- a/drivers/isdn/hardware/mISDN/mISDNinfineon.c +++ b/drivers/isdn/hardware/mISDN/mISDNinfineon.c @@ -1133,6 +1133,7 @@ inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (err) { kfree(sc); release_card(card); + break; } else card->sc[i - 1] = sc; } -- cgit v1.2.2 From 3e5981774755f2f967cd1d3f3898576cff20e565 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 2 Feb 2010 12:43:46 +0000 Subject: isdn: mISDN, don't compile unused stuff Remove these compiler warnings: drivers/isdn/hardware/mISDN/w6692.c:534: warning: `setvolume' defined but not used drivers/isdn/hardware/mISDN/w6692.c:561: warning: `enable_pots' defined but not used by moving the functions inside #if 0 ... #endif. And an alternative is to remove them completely if nobody has plans to use them. Signed-off-by: Jiri Slaby Cc: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/w6692.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/isdn') diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c index d3f1077b709b..2952a58c7a61 100644 --- a/drivers/isdn/hardware/mISDN/w6692.c +++ b/drivers/isdn/hardware/mISDN/w6692.c @@ -529,6 +529,7 @@ W6692_fill_Bfifo(struct w6692_ch *wch) } } +#if 0 static int setvolume(struct w6692_ch *wch, int mic, struct sk_buff *skb) { @@ -571,6 +572,7 @@ enable_pots(struct w6692_ch *wch) WriteW6692(card, W_PCTL, card->pctl); return 0; } +#endif static int disable_pots(struct w6692_ch *wch) -- cgit v1.2.2 From 650b2ef5d7f1378f65e6a313909d783e4b6477ed Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 2 Feb 2010 12:43:47 +0000 Subject: mISDN: positive error return should be negative in mode_hfcmulti() The error return should be negative. Its only caller that acts upon its return, handle_bmsg(), transmits the positive error but can also return negative errors. Signed-off-by: Roel Kluin Cc: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/hfcmulti.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index 1a1420d7a828..ad36df9b759c 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c @@ -2846,7 +2846,7 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx, int conf; if (ch < 0 || ch > 31) - return EINVAL; + return -EINVAL; oslot_tx = hc->chan[ch].slot_tx; oslot_rx = hc->chan[ch].slot_rx; conf = hc->chan[ch].conf; -- cgit v1.2.2 From edf86baae2e92bc03615086b2a341cd6d56c20f2 Mon Sep 17 00:00:00 2001 From: Adam Buchbinder Date: Fri, 11 Dec 2009 16:35:41 -0500 Subject: Fix misspellings of "separate" in strings. Some string messages misspell "separate"; this fixes them. No change in functionality. Signed-off-by: Adam Buchbinder Signed-off-by: Jiri Kosina --- drivers/isdn/mISDN/l1oip_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c index f1e8af54dff0..0843fcf8b381 100644 --- a/drivers/isdn/mISDN/l1oip_core.c +++ b/drivers/isdn/mISDN/l1oip_core.c @@ -1509,7 +1509,7 @@ l1oip_init(void) printk(KERN_DEBUG "%s: interface %d is %s with %s.\n", __func__, l1oip_cnt, pri ? "PRI" : "BRI", bundle ? "bundled IP packet for all B-channels" : - "seperate IP packets for every B-channel"); + "separate IP packets for every B-channel"); hc = kzalloc(sizeof(struct l1oip), GFP_ATOMIC); if (!hc) { -- cgit v1.2.2 From 8885074038b219b90cb0f5cd1a049ba80c7e815b Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Tue, 22 Dec 2009 09:27:06 +0100 Subject: isdn/hardware: add __init/__exit macros to mISDNisar.c Trivial patch which adds the __init/__exit macros to the module_init/ module_exit functions of drivers/isdn/hardware/mISDN/mISDNisar.c Signed-off-by: Peter Huewe Signed-off-by: Jiri Kosina --- drivers/isdn/hardware/mISDN/mISDNisar.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c index 09095c747110..f0bc6fa95809 100644 --- a/drivers/isdn/hardware/mISDN/mISDNisar.c +++ b/drivers/isdn/hardware/mISDN/mISDNisar.c @@ -1712,13 +1712,13 @@ mISDNisar_init(struct isar_hw *isar, void *hw) } EXPORT_SYMBOL(mISDNisar_init); -static int isar_mod_init(void) +static int __init isar_mod_init(void) { pr_notice("mISDN: ISAR driver Rev. %s\n", ISAR_REV); return 0; } -static void isar_mod_cleanup(void) +static void __exit isar_mod_cleanup(void) { pr_notice("mISDN: ISAR module unloaded\n"); } -- cgit v1.2.2 From 3d956d1dfffef3b19d743aa1a443ab5a300051cb Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Tue, 22 Dec 2009 09:41:42 +0100 Subject: isdn/mISDN: add __init/__exit macros to dsp_core.c Trivial patch which adds the __init/__exit macros to the module_init/ module_exit functions of drivers/isdn/mISDN/dsp_core.c Signed-off-by: Peter Huewe Signed-off-by: Jiri Kosina --- drivers/isdn/mISDN/dsp_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c index 43ff4d3b046e..6eac588e0a37 100644 --- a/drivers/isdn/mISDN/dsp_core.c +++ b/drivers/isdn/mISDN/dsp_core.c @@ -1114,7 +1114,7 @@ static struct Bprotocol DSP = { .create = dspcreate }; -static int dsp_init(void) +static int __init dsp_init(void) { int err; int tics; @@ -1212,7 +1212,7 @@ static int dsp_init(void) } -static void dsp_cleanup(void) +static void __exit dsp_cleanup(void) { mISDN_unregister_Bprotocol(&DSP); -- cgit v1.2.2 From 9ddc5b6f18fbac07d2746566b73b89e89fdd4e6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 20 Jan 2010 17:02:24 +0100 Subject: tree-wide: fix typos "ammount" -> "amount" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König Signed-off-by: Jiri Kosina --- drivers/isdn/sc/hardware.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/sc/hardware.h b/drivers/isdn/sc/hardware.h index 9e6d5302bf8e..627324856ead 100644 --- a/drivers/isdn/sc/hardware.h +++ b/drivers/isdn/sc/hardware.h @@ -87,7 +87,7 @@ #define BRI_CHANNELS 2 /* Number of B channels */ #define BRI_BASEPG_VAL 0x98 #define BRI_MAGIC 0x60000 /* Magic Number */ -#define BRI_MEMSIZE 0x10000 /* Ammount of RAM (64K) */ +#define BRI_MEMSIZE 0x10000 /* Amount of RAM (64K) */ #define BRI_PARTNO "72-029" #define BRI_FEATURES ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L3_TRANS; /* -- cgit v1.2.2 From 1537a3638cbf741d3826c1002026cce487a6bee0 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 29 Jan 2010 15:57:49 +0800 Subject: tree-wide: fix 'lenght' typo in comments and code Some misspelled occurences of 'octet' and some comments were also fixed as I was on it. Signed-off-by: Daniel Mack Cc: Jiri Kosina Cc: Joe Perches Cc: Junio C Hamano Signed-off-by: Jiri Kosina --- drivers/isdn/mISDN/l1oip_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c index 0843fcf8b381..325b1ad7d4b8 100644 --- a/drivers/isdn/mISDN/l1oip_core.c +++ b/drivers/isdn/mISDN/l1oip_core.c @@ -477,7 +477,7 @@ l1oip_socket_parse(struct l1oip *hc, struct sockaddr_in *sin, u8 *buf, int len) printk(KERN_DEBUG "%s: received frame, parsing... (%d)\n", __func__, len); - /* check lenght */ + /* check length */ if (len < 1+1+2) { printk(KERN_WARNING "%s: packet error - length %d below " "4 bytes\n", __func__, len); -- cgit v1.2.2 From 3ad2f3fbb961429d2aa627465ae4829758bc7e07 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 3 Feb 2010 08:01:28 +0800 Subject: tree-wide: Assorted spelling fixes In particular, several occurances of funny versions of 'success', 'unknown', 'therefore', 'acknowledge', 'argument', 'achieve', 'address', 'beginning', 'desirable', 'separate' and 'necessary' are fixed. Signed-off-by: Daniel Mack Cc: Joe Perches Cc: Junio C Hamano Signed-off-by: Jiri Kosina --- drivers/isdn/i4l/isdn_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index adb1e8c36b46..00c60e2e0ff7 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -1347,7 +1347,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) /* * isdn net devices manage lots of configuration variables as linked lists. * Those lists must only be manipulated from user space. Some of the ioctl's - * service routines access user space and are not atomic. Therefor, ioctl's + * service routines access user space and are not atomic. Therefore, ioctl's * manipulating the lists and ioctl's sleeping while accessing the lists * are serialized by means of a semaphore. */ -- cgit v1.2.2 From c947862f9126983537a4cc11e07d26882d60b7e7 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:05 +0000 Subject: CAPI: Fix leaks in capifs_new_ncci When something went wrong during capifs_new_ncci, the looked up dentry was not properly released. Neither was the allocated inode. Refactor the function to avoid leaks. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capifs.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c index 9f8f67b6c07f..dc68fcb122a0 100644 --- a/drivers/isdn/capi/capifs.c +++ b/drivers/isdn/capi/capifs.c @@ -152,22 +152,33 @@ static struct dentry *get_node(int num) void capifs_new_ncci(unsigned int number, dev_t device) { struct dentry *dentry; - struct inode *inode = new_inode(capifs_mnt->mnt_sb); - if (!inode) - return; - inode->i_ino = number+2; + struct inode *inode; dentry = get_node(number); + if (IS_ERR(dentry)) + goto unlock_out; + + if (dentry->d_inode) { + dput(dentry); + goto unlock_out; + } + + inode = new_inode(capifs_mnt->mnt_sb); + if (!inode) { + dput(dentry); + goto unlock_out; + } /* config contents is protected by root's i_mutex */ inode->i_uid = config.setuid ? config.uid : current_fsuid(); inode->i_gid = config.setgid ? config.gid : current_fsgid(); inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; + inode->i_ino = number + 2; init_special_inode(inode, S_IFCHR|config.mode, device); - //inode->i_op = &capifs_file_inode_operations; - if (!IS_ERR(dentry) && !dentry->d_inode) - d_instantiate(dentry, inode); + d_instantiate(dentry, inode); + +unlock_out: mutex_unlock(&capifs_root->d_inode->i_mutex); } -- cgit v1.2.2 From 90926f0e58dcd9f4ca877961000568a3be787f2f Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:06 +0000 Subject: CAPI: Sanitize capifs API Instead of looking up the dentry of an NCCI node again in capifs_free_ncci pass the pointer via the capifs user. This patch also reduces the #ifdef mess in capi.c a bit as far as capifs was causing it. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 14 ++++++------- drivers/isdn/capi/capifs.c | 50 +++++++++++++++++++++++++++------------------- drivers/isdn/capi/capifs.h | 21 +++++++++++++++++-- 3 files changed, 54 insertions(+), 31 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 79f9364aded6..dc5ac52986ee 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -42,9 +42,8 @@ #include #include #include -#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) + #include "capifs.h" -#endif static char *revision = "$Revision: 1.1.2.7 $"; @@ -96,6 +95,7 @@ struct capiminor { struct list_head list; struct capincci *nccip; unsigned int minor; + struct dentry *capifs_dentry; struct capi20_appl *ap; u32 ncci; @@ -328,9 +328,9 @@ static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci) #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "set mp->nccip\n"); #endif -#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) - capifs_new_ncci(mp->minor, MKDEV(capi_ttymajor, mp->minor)); -#endif + mp->capifs_dentry = + capifs_new_ncci(mp->minor, + MKDEV(capi_ttymajor, mp->minor)); } #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ for (pp=&cdev->nccis; *pp; pp = &(*pp)->next) @@ -353,9 +353,7 @@ static void capincci_free(struct capidev *cdev, u32 ncci) *pp = (*pp)->next; #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE if ((mp = np->minorp) != NULL) { -#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) - capifs_free_ncci(mp->minor); -#endif + capifs_free_ncci(mp->capifs_dentry); if (mp->tty) { mp->nccip = NULL; #ifdef _DEBUG_REFCOUNT diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c index dc68fcb122a0..91aafadd413f 100644 --- a/drivers/isdn/capi/capifs.c +++ b/drivers/isdn/capi/capifs.c @@ -141,31 +141,32 @@ static struct file_system_type capifs_fs_type = { .kill_sb = kill_anon_super, }; -static struct dentry *get_node(int num) -{ - char s[10]; - struct dentry *root = capifs_root; - mutex_lock(&root->d_inode->i_mutex); - return lookup_one_len(s, root, sprintf(s, "%d", num)); -} - -void capifs_new_ncci(unsigned int number, dev_t device) +struct dentry *capifs_new_ncci(unsigned int number, dev_t device) { struct dentry *dentry; struct inode *inode; + char name[10]; + int namelen; - dentry = get_node(number); - if (IS_ERR(dentry)) + mutex_lock(&capifs_root->d_inode->i_mutex); + + namelen = sprintf(name, "%d", number); + dentry = lookup_one_len(name, capifs_root, namelen); + if (IS_ERR(dentry)) { + dentry = NULL; goto unlock_out; + } if (dentry->d_inode) { dput(dentry); + dentry = NULL; goto unlock_out; } inode = new_inode(capifs_mnt->mnt_sb); if (!inode) { dput(dentry); + dentry = NULL; goto unlock_out; } @@ -177,24 +178,31 @@ void capifs_new_ncci(unsigned int number, dev_t device) init_special_inode(inode, S_IFCHR|config.mode, device); d_instantiate(dentry, inode); + dget(dentry); unlock_out: mutex_unlock(&capifs_root->d_inode->i_mutex); + + return dentry; } -void capifs_free_ncci(unsigned int number) +void capifs_free_ncci(struct dentry *dentry) { - struct dentry *dentry = get_node(number); - - if (!IS_ERR(dentry)) { - struct inode *inode = dentry->d_inode; - if (inode) { - inode->i_nlink--; - d_delete(dentry); - dput(dentry); - } + struct inode *inode; + + if (!dentry) + return; + + mutex_lock(&capifs_root->d_inode->i_mutex); + + inode = dentry->d_inode; + if (inode) { + drop_nlink(inode); + d_delete(dentry); dput(dentry); } + dput(dentry); + mutex_unlock(&capifs_root->d_inode->i_mutex); } diff --git a/drivers/isdn/capi/capifs.h b/drivers/isdn/capi/capifs.h index d0bd4c3c430a..e193d1189531 100644 --- a/drivers/isdn/capi/capifs.h +++ b/drivers/isdn/capi/capifs.h @@ -7,5 +7,22 @@ * */ -void capifs_new_ncci(unsigned int num, dev_t device); -void capifs_free_ncci(unsigned int num); +#include + +#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) + +struct dentry *capifs_new_ncci(unsigned int num, dev_t device); +void capifs_free_ncci(struct dentry *dentry); + +#else + +static inline struct dentry *capifs_new_ncci(unsigned int num, dev_t device) +{ + return NULL; +} + +static inline void capifs_free_ncci(struct dentry *dentry) +{ +} + +#endif -- cgit v1.2.2 From 07ad603ab8e3cc35762c15043b59a6ef76542454 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:07 +0000 Subject: CAPI: Eliminate capifs_root variable capifs_mnt->mnt_sb->s_root already contains what we need. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capifs.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c index 91aafadd413f..6ae0edf29c85 100644 --- a/drivers/isdn/capi/capifs.c +++ b/drivers/isdn/capi/capifs.c @@ -32,7 +32,6 @@ static char *revision = "$Revision: 1.1.2.3 $"; #define CAPIFS_SUPER_MAGIC (('C'<<8)|'N') static struct vfsmount *capifs_mnt; -static struct dentry *capifs_root; static struct { int setuid; @@ -118,7 +117,7 @@ capifs_fill_super(struct super_block *s, void *data, int silent) inode->i_fop = &simple_dir_operations; inode->i_nlink = 2; - capifs_root = s->s_root = d_alloc_root(inode); + s->s_root = d_alloc_root(inode); if (s->s_root) return 0; @@ -143,15 +142,17 @@ static struct file_system_type capifs_fs_type = { struct dentry *capifs_new_ncci(unsigned int number, dev_t device) { + struct super_block *s = capifs_mnt->mnt_sb; + struct dentry *root = s->s_root; struct dentry *dentry; struct inode *inode; char name[10]; int namelen; - mutex_lock(&capifs_root->d_inode->i_mutex); + mutex_lock(&root->d_inode->i_mutex); namelen = sprintf(name, "%d", number); - dentry = lookup_one_len(name, capifs_root, namelen); + dentry = lookup_one_len(name, root, namelen); if (IS_ERR(dentry)) { dentry = NULL; goto unlock_out; @@ -163,7 +164,7 @@ struct dentry *capifs_new_ncci(unsigned int number, dev_t device) goto unlock_out; } - inode = new_inode(capifs_mnt->mnt_sb); + inode = new_inode(s); if (!inode) { dput(dentry); dentry = NULL; @@ -181,19 +182,20 @@ struct dentry *capifs_new_ncci(unsigned int number, dev_t device) dget(dentry); unlock_out: - mutex_unlock(&capifs_root->d_inode->i_mutex); + mutex_unlock(&root->d_inode->i_mutex); return dentry; } void capifs_free_ncci(struct dentry *dentry) { + struct dentry *root = capifs_mnt->mnt_sb->s_root; struct inode *inode; if (!dentry) return; - mutex_lock(&capifs_root->d_inode->i_mutex); + mutex_lock(&root->d_inode->i_mutex); inode = dentry->d_inode; if (inode) { @@ -203,7 +205,7 @@ void capifs_free_ncci(struct dentry *dentry) } dput(dentry); - mutex_unlock(&capifs_root->d_inode->i_mutex); + mutex_unlock(&root->d_inode->i_mutex); } static int __init capifs_init(void) -- cgit v1.2.2 From e11e7ac1ecac6b25439c003c5ca661cd399ec35d Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:08 +0000 Subject: CAPI: Pin capifs instead of mounting it Auto-mounting the capifs during module init prevents unloading its module. Instead, pin the filesystem as long as some NCCI node exists. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capifs.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c index 6ae0edf29c85..51c01efe2fe4 100644 --- a/drivers/isdn/capi/capifs.c +++ b/drivers/isdn/capi/capifs.c @@ -32,6 +32,7 @@ static char *revision = "$Revision: 1.1.2.3 $"; #define CAPIFS_SUPER_MAGIC (('C'<<8)|'N') static struct vfsmount *capifs_mnt; +static int capifs_mnt_count; static struct { int setuid; @@ -140,7 +141,7 @@ static struct file_system_type capifs_fs_type = { .kill_sb = kill_anon_super, }; -struct dentry *capifs_new_ncci(unsigned int number, dev_t device) +static struct dentry *new_ncci(unsigned int number, dev_t device) { struct super_block *s = capifs_mnt->mnt_sb; struct dentry *root = s->s_root; @@ -187,6 +188,20 @@ unlock_out: return dentry; } +struct dentry *capifs_new_ncci(unsigned int number, dev_t device) +{ + struct dentry *dentry; + + if (simple_pin_fs(&capifs_fs_type, &capifs_mnt, &capifs_mnt_count) < 0) + return NULL; + + dentry = new_ncci(number, device); + if (!dentry) + simple_release_fs(&capifs_mnt, &capifs_mnt_count); + + return dentry; +} + void capifs_free_ncci(struct dentry *dentry) { struct dentry *root = capifs_mnt->mnt_sb->s_root; @@ -206,6 +221,8 @@ void capifs_free_ncci(struct dentry *dentry) dput(dentry); mutex_unlock(&root->d_inode->i_mutex); + + simple_release_fs(&capifs_mnt, &capifs_mnt_count); } static int __init capifs_init(void) @@ -222,13 +239,6 @@ static int __init capifs_init(void) strcpy(rev, "1.0"); err = register_filesystem(&capifs_fs_type); - if (!err) { - capifs_mnt = kern_mount(&capifs_fs_type); - if (IS_ERR(capifs_mnt)) { - err = PTR_ERR(capifs_mnt); - unregister_filesystem(&capifs_fs_type); - } - } if (!err) printk(KERN_NOTICE "capifs: Rev %s\n", rev); return err; @@ -237,7 +247,6 @@ static int __init capifs_init(void) static void __exit capifs_exit(void) { unregister_filesystem(&capifs_fs_type); - mntput(capifs_mnt); } EXPORT_SYMBOL(capifs_new_ncci); -- cgit v1.2.2 From 88549d6b76346e677da8d2d52b37615df18a4345 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:09 +0000 Subject: CAPI: Reduce chattiness during module loading/removal The CVS revisions dumped by all CAPI modules are meaningless today. And that some CAPI module is loaded or removed does not necessarily deserve a message. Just keep the message of the central module, capi.ko, drop the rest. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 19 +++---------------- drivers/isdn/capi/capidrv.c | 26 -------------------------- drivers/isdn/capi/capifs.c | 20 +------------------- drivers/isdn/capi/kcapi.c | 27 +++++---------------------- 4 files changed, 9 insertions(+), 83 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index dc5ac52986ee..3b077978c496 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -45,8 +45,6 @@ #include "capifs.h" -static char *revision = "$Revision: 1.1.2.7 $"; - MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface"); MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); @@ -1489,21 +1487,11 @@ static void __exit proc_exit(void) /* -------- init function and module interface ---------------------- */ -static char rev[32]; - static int __init capi_init(void) { - char *p; - char *compileinfo; + const char *compileinfo; int major_ret; - if ((p = strchr(revision, ':')) != NULL && p[1]) { - strlcpy(rev, p + 2, sizeof(rev)); - if ((p = strchr(rev, '$')) != NULL && p > rev) - *(p-1) = 0; - } else - strcpy(rev, "1.0"); - major_ret = register_chrdev(capi_major, "capi20", &capi_fops); if (major_ret < 0) { printk(KERN_ERR "capi20: unable to get major %d\n", capi_major); @@ -1537,8 +1525,8 @@ static int __init capi_init(void) #else compileinfo = " (no middleware)"; #endif - printk(KERN_NOTICE "capi20: Rev %s: started up with major %d%s\n", - rev, capi_major, compileinfo); + printk(KERN_NOTICE "CAPI 2.0 started up with major %d%s\n", + capi_major, compileinfo); return 0; } @@ -1554,7 +1542,6 @@ static void __exit capi_exit(void) #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE capinc_tty_exit(); #endif - printk(KERN_NOTICE "capi: Rev %s: unloaded\n", rev); } module_init(capi_init); diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c index bb450152fb74..7d8899ad5796 100644 --- a/drivers/isdn/capi/capidrv.c +++ b/drivers/isdn/capi/capidrv.c @@ -35,7 +35,6 @@ #include #include "capidrv.h" -static char *revision = "$Revision: 1.1.2.2 $"; static int debugmode = 0; MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux"); @@ -2266,19 +2265,9 @@ static void __exit proc_exit(void) static int __init capidrv_init(void) { capi_profile profile; - char rev[32]; - char *p; u32 ncontr, contr; u16 errcode; - if ((p = strchr(revision, ':')) != NULL && p[1]) { - strncpy(rev, p + 2, sizeof(rev)); - rev[sizeof(rev)-1] = 0; - if ((p = strchr(rev, '$')) != NULL && p > rev) - *(p-1) = 0; - } else - strcpy(rev, "1.0"); - global.ap.rparam.level3cnt = -2; /* number of bchannels twice */ global.ap.rparam.datablkcnt = 16; global.ap.rparam.datablklen = 2048; @@ -2306,29 +2295,14 @@ static int __init capidrv_init(void) } proc_init(); - printk(KERN_NOTICE "capidrv: Rev %s: loaded\n", rev); return 0; } static void __exit capidrv_exit(void) { - char rev[32]; - char *p; - - if ((p = strchr(revision, ':')) != NULL) { - strncpy(rev, p + 1, sizeof(rev)); - rev[sizeof(rev)-1] = 0; - if ((p = strchr(rev, '$')) != NULL) - *p = 0; - } else { - strcpy(rev, " ??? "); - } - capi20_release(&global.ap); proc_exit(); - - printk(KERN_NOTICE "capidrv: Rev%s: unloaded\n", rev); } module_init(capidrv_init); diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c index 51c01efe2fe4..8596bd1a4d26 100644 --- a/drivers/isdn/capi/capifs.c +++ b/drivers/isdn/capi/capifs.c @@ -25,10 +25,6 @@ MODULE_LICENSE("GPL"); /* ------------------------------------------------------------------ */ -static char *revision = "$Revision: 1.1.2.3 $"; - -/* ------------------------------------------------------------------ */ - #define CAPIFS_SUPER_MAGIC (('C'<<8)|'N') static struct vfsmount *capifs_mnt; @@ -227,21 +223,7 @@ void capifs_free_ncci(struct dentry *dentry) static int __init capifs_init(void) { - char rev[32]; - char *p; - int err; - - if ((p = strchr(revision, ':')) != NULL && p[1]) { - strlcpy(rev, p + 2, sizeof(rev)); - if ((p = strchr(rev, '$')) != NULL && p > rev) - *(p-1) = 0; - } else - strcpy(rev, "1.0"); - - err = register_filesystem(&capifs_fs_type); - if (!err) - printk(KERN_NOTICE "capifs: Rev %s\n", rev); - return err; + return register_filesystem(&capifs_fs_type); } static void __exit capifs_exit(void) diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index b0bacf377c18..ef564ee1c06c 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -35,10 +35,6 @@ #endif #include -static char *revision = "$Revision: 1.1.2.8 $"; - -/* ------------------------------------------------------------- */ - static int showcapimsgs = 0; MODULE_DESCRIPTION("CAPI4Linux: kernel CAPI layer"); @@ -1165,25 +1161,12 @@ EXPORT_SYMBOL(capi20_set_callback); static int __init kcapi_init(void) { - char *p; - char rev[32]; - int ret; - - ret = cdebug_init(); - if (ret) - return ret; - kcapi_proc_init(); + int err; - if ((p = strchr(revision, ':')) != NULL && p[1]) { - strlcpy(rev, p + 2, sizeof(rev)); - if ((p = strchr(rev, '$')) != NULL && p > rev) - *(p-1) = 0; - } else - strcpy(rev, "1.0"); - - printk(KERN_NOTICE "CAPI Subsystem Rev %s\n", rev); - - return 0; + err = cdebug_init(); + if (!err) + kcapi_proc_init(); + return err; } static void __exit kcapi_exit(void) -- cgit v1.2.2 From 522530311b35ec8fc4785062441dd2d63967ac55 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:10 +0000 Subject: CAPI: Call a controller 'controller', not 'card' At least for our internal use, fix the misnomers that refer to a CAPI controller as 'card'. No functional changes. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/kcapi.c | 320 +++++++++++++++++++++-------------------- drivers/isdn/capi/kcapi.h | 8 +- drivers/isdn/capi/kcapi_proc.c | 17 ++- 3 files changed, 177 insertions(+), 168 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index ef564ee1c06c..f37c13b4ddc7 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -67,24 +67,24 @@ static DEFINE_RWLOCK(application_lock); static DEFINE_MUTEX(controller_mutex); struct capi20_appl *capi_applications[CAPI_MAXAPPL]; -struct capi_ctr *capi_cards[CAPI_MAXCONTR]; +struct capi_ctr *capi_controller[CAPI_MAXCONTR]; -static int ncards; +static int ncontrollers; /* -------- controller ref counting -------------------------------------- */ static inline struct capi_ctr * -capi_ctr_get(struct capi_ctr *card) +capi_ctr_get(struct capi_ctr *ctr) { - if (!try_module_get(card->owner)) + if (!try_module_get(ctr->owner)) return NULL; - return card; + return ctr; } static inline void -capi_ctr_put(struct capi_ctr *card) +capi_ctr_put(struct capi_ctr *ctr) { - module_put(card->owner); + module_put(ctr->owner); } /* ------------------------------------------------------------- */ @@ -94,7 +94,7 @@ static inline struct capi_ctr *get_capi_ctr_by_nr(u16 contr) if (contr - 1 >= CAPI_MAXCONTR) return NULL; - return capi_cards[contr - 1]; + return capi_controller[contr - 1]; } static inline struct capi20_appl *get_capi_appl_by_nr(u16 applid) @@ -144,46 +144,48 @@ static inline int capi_subcmd_valid(u8 subcmd) /* ------------------------------------------------------------ */ -static void register_appl(struct capi_ctr *card, u16 applid, capi_register_params *rparam) +static void +register_appl(struct capi_ctr *ctr, u16 applid, capi_register_params *rparam) { - card = capi_ctr_get(card); + ctr = capi_ctr_get(ctr); - if (card) - card->register_appl(card, applid, rparam); + if (ctr) + ctr->register_appl(ctr, applid, rparam); else - printk(KERN_WARNING "%s: cannot get card resources\n", __func__); + printk(KERN_WARNING "%s: cannot get controller resources\n", + __func__); } -static void release_appl(struct capi_ctr *card, u16 applid) +static void release_appl(struct capi_ctr *ctr, u16 applid) { DBG("applid %#x", applid); - card->release_appl(card, applid); - capi_ctr_put(card); + ctr->release_appl(ctr, applid); + capi_ctr_put(ctr); } /* -------- KCI_CONTRUP --------------------------------------- */ static void notify_up(u32 contr) { - struct capi_ctr *card = get_capi_ctr_by_nr(contr); + struct capi_ctr *ctr = get_capi_ctr_by_nr(contr); struct capi20_appl *ap; u16 applid; if (showcapimsgs & 1) { printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr); } - if (!card) { + if (!ctr) { printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); return; } for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { ap = get_capi_appl_by_nr(applid); if (!ap || ap->release_in_progress) continue; - register_appl(card, applid, &ap->rparam); + register_appl(ctr, applid, &ap->rparam); if (ap->callback && !ap->release_in_progress) - ap->callback(KCI_CONTRUP, contr, &card->profile); + ap->callback(KCI_CONTRUP, contr, &ctr->profile); } } @@ -269,14 +271,15 @@ static void recv_handler(struct work_struct *work) /** * capi_ctr_handle_message() - handle incoming CAPI message - * @card: controller descriptor structure. + * @ctr: controller descriptor structure. * @appl: application ID. * @skb: message. * * Called by hardware driver to pass a CAPI message to the application. */ -void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *skb) +void capi_ctr_handle_message(struct capi_ctr *ctr, u16 appl, + struct sk_buff *skb) { struct capi20_appl *ap; int showctl = 0; @@ -284,43 +287,45 @@ void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *s unsigned long flags; _cdebbuf *cdb; - if (card->cardstate != CARD_RUNNING) { + if (ctr->state != CAPI_CTR_RUNNING) { cdb = capi_message2str(skb->data); if (cdb) { printk(KERN_INFO "kcapi: controller [%03d] not active, got: %s", - card->cnr, cdb->buf); + ctr->cnr, cdb->buf); cdebbuf_free(cdb); } else printk(KERN_INFO "kcapi: controller [%03d] not active, cannot trace\n", - card->cnr); + ctr->cnr); goto error; } cmd = CAPIMSG_COMMAND(skb->data); subcmd = CAPIMSG_SUBCOMMAND(skb->data); if (cmd == CAPI_DATA_B3 && subcmd == CAPI_IND) { - card->nrecvdatapkt++; - if (card->traceflag > 2) showctl |= 2; + ctr->nrecvdatapkt++; + if (ctr->traceflag > 2) + showctl |= 2; } else { - card->nrecvctlpkt++; - if (card->traceflag) showctl |= 2; + ctr->nrecvctlpkt++; + if (ctr->traceflag) + showctl |= 2; } - showctl |= (card->traceflag & 1); + showctl |= (ctr->traceflag & 1); if (showctl & 2) { if (showctl & 1) { printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u\n", - card->cnr, CAPIMSG_APPID(skb->data), + ctr->cnr, CAPIMSG_APPID(skb->data), capi_cmd2str(cmd, subcmd), CAPIMSG_LEN(skb->data)); } else { cdb = capi_message2str(skb->data); if (cdb) { printk(KERN_DEBUG "kcapi: got [%03d] %s\n", - card->cnr, cdb->buf); + ctr->cnr, cdb->buf); cdebbuf_free(cdb); } else printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u, cannot trace\n", - card->cnr, CAPIMSG_APPID(skb->data), + ctr->cnr, CAPIMSG_APPID(skb->data), capi_cmd2str(cmd, subcmd), CAPIMSG_LEN(skb->data)); } @@ -356,74 +361,75 @@ EXPORT_SYMBOL(capi_ctr_handle_message); /** * capi_ctr_ready() - signal CAPI controller ready - * @card: controller descriptor structure. + * @ctr: controller descriptor structure. * * Called by hardware driver to signal that the controller is up and running. */ -void capi_ctr_ready(struct capi_ctr * card) +void capi_ctr_ready(struct capi_ctr *ctr) { - card->cardstate = CARD_RUNNING; + ctr->state = CAPI_CTR_RUNNING; - printk(KERN_NOTICE "kcapi: card [%03d] \"%s\" ready.\n", - card->cnr, card->name); + printk(KERN_NOTICE "kcapi: controller [%03d] \"%s\" ready.\n", + ctr->cnr, ctr->name); - notify_push(KCI_CONTRUP, card->cnr, 0, 0); + notify_push(KCI_CONTRUP, ctr->cnr, 0, 0); } EXPORT_SYMBOL(capi_ctr_ready); /** * capi_ctr_down() - signal CAPI controller not ready - * @card: controller descriptor structure. + * @ctr: controller descriptor structure. * * Called by hardware driver to signal that the controller is down and * unavailable for use. */ -void capi_ctr_down(struct capi_ctr * card) +void capi_ctr_down(struct capi_ctr *ctr) { u16 appl; DBG(""); - if (card->cardstate == CARD_DETECTED) + if (ctr->state == CAPI_CTR_DETECTED) return; - card->cardstate = CARD_DETECTED; + ctr->state = CAPI_CTR_DETECTED; - memset(card->manu, 0, sizeof(card->manu)); - memset(&card->version, 0, sizeof(card->version)); - memset(&card->profile, 0, sizeof(card->profile)); - memset(card->serial, 0, sizeof(card->serial)); + memset(ctr->manu, 0, sizeof(ctr->manu)); + memset(&ctr->version, 0, sizeof(ctr->version)); + memset(&ctr->profile, 0, sizeof(ctr->profile)); + memset(ctr->serial, 0, sizeof(ctr->serial)); for (appl = 1; appl <= CAPI_MAXAPPL; appl++) { struct capi20_appl *ap = get_capi_appl_by_nr(appl); if (!ap || ap->release_in_progress) continue; - capi_ctr_put(card); + capi_ctr_put(ctr); } - printk(KERN_NOTICE "kcapi: card [%03d] down.\n", card->cnr); + printk(KERN_NOTICE "kcapi: controller [%03d] down.\n", ctr->cnr); - notify_push(KCI_CONTRDOWN, card->cnr, 0, 0); + notify_push(KCI_CONTRDOWN, ctr->cnr, 0, 0); } EXPORT_SYMBOL(capi_ctr_down); /** * capi_ctr_suspend_output() - suspend controller - * @card: controller descriptor structure. + * @ctr: controller descriptor structure. * * Called by hardware driver to stop data flow. */ -void capi_ctr_suspend_output(struct capi_ctr *card) +void capi_ctr_suspend_output(struct capi_ctr *ctr) { - if (!card->blocked) { - printk(KERN_DEBUG "kcapi: card [%03d] suspend\n", card->cnr); - card->blocked = 1; + if (!ctr->blocked) { + printk(KERN_DEBUG "kcapi: controller [%03d] suspend\n", + ctr->cnr); + ctr->blocked = 1; } } @@ -431,16 +437,17 @@ EXPORT_SYMBOL(capi_ctr_suspend_output); /** * capi_ctr_resume_output() - resume controller - * @card: controller descriptor structure. + * @ctr: controller descriptor structure. * * Called by hardware driver to resume data flow. */ -void capi_ctr_resume_output(struct capi_ctr *card) +void capi_ctr_resume_output(struct capi_ctr *ctr) { - if (card->blocked) { - printk(KERN_DEBUG "kcapi: card [%03d] resume\n", card->cnr); - card->blocked = 0; + if (ctr->blocked) { + printk(KERN_DEBUG "kcapi: controller [%03d] resumed\n", + ctr->cnr); + ctr->blocked = 0; } } @@ -450,21 +457,20 @@ EXPORT_SYMBOL(capi_ctr_resume_output); /** * attach_capi_ctr() - register CAPI controller - * @card: controller descriptor structure. + * @ctr: controller descriptor structure. * * Called by hardware driver to register a controller with the CAPI subsystem. * Return value: 0 on success, error code < 0 on error */ -int -attach_capi_ctr(struct capi_ctr *card) +int attach_capi_ctr(struct capi_ctr *ctr) { int i; mutex_lock(&controller_mutex); for (i = 0; i < CAPI_MAXCONTR; i++) { - if (capi_cards[i] == NULL) + if (!capi_controller[i]) break; } if (i == CAPI_MAXCONTR) { @@ -472,25 +478,25 @@ attach_capi_ctr(struct capi_ctr *card) printk(KERN_ERR "kcapi: out of controller slots\n"); return -EBUSY; } - capi_cards[i] = card; + capi_controller[i] = ctr; mutex_unlock(&controller_mutex); - card->nrecvctlpkt = 0; - card->nrecvdatapkt = 0; - card->nsentctlpkt = 0; - card->nsentdatapkt = 0; - card->cnr = i + 1; - card->cardstate = CARD_DETECTED; - card->blocked = 0; - card->traceflag = showcapimsgs; - - sprintf(card->procfn, "capi/controllers/%d", card->cnr); - card->procent = proc_create_data(card->procfn, 0, NULL, card->proc_fops, card); - - ncards++; - printk(KERN_NOTICE "kcapi: Controller [%03d]: %s attached\n", - card->cnr, card->name); + ctr->nrecvctlpkt = 0; + ctr->nrecvdatapkt = 0; + ctr->nsentctlpkt = 0; + ctr->nsentdatapkt = 0; + ctr->cnr = i + 1; + ctr->state = CAPI_CTR_DETECTED; + ctr->blocked = 0; + ctr->traceflag = showcapimsgs; + + sprintf(ctr->procfn, "capi/controllers/%d", ctr->cnr); + ctr->procent = proc_create_data(ctr->procfn, 0, NULL, ctr->proc_fops, ctr); + + ncontrollers++; + printk(KERN_NOTICE "kcapi: controller [%03d]: %s attached\n", + ctr->cnr, ctr->name); return 0; } @@ -498,27 +504,27 @@ EXPORT_SYMBOL(attach_capi_ctr); /** * detach_capi_ctr() - unregister CAPI controller - * @card: controller descriptor structure. + * @ctr: controller descriptor structure. * * Called by hardware driver to remove the registration of a controller * with the CAPI subsystem. * Return value: 0 on success, error code < 0 on error */ -int detach_capi_ctr(struct capi_ctr *card) +int detach_capi_ctr(struct capi_ctr *ctr) { - if (card->cardstate != CARD_DETECTED) - capi_ctr_down(card); + if (ctr->state != CAPI_CTR_DETECTED) + capi_ctr_down(ctr); - ncards--; + ncontrollers--; - if (card->procent) { - remove_proc_entry(card->procfn, NULL); - card->procent = NULL; + if (ctr->procent) { + remove_proc_entry(ctr->procfn, NULL); + ctr->procent = NULL; } - capi_cards[card->cnr - 1] = NULL; - printk(KERN_NOTICE "kcapi: Controller [%03d]: %s unregistered\n", - card->cnr, card->name); + capi_controller[ctr->cnr - 1] = NULL; + printk(KERN_NOTICE "kcapi: controller [%03d]: %s unregistered\n", + ctr->cnr, ctr->name); return 0; } @@ -576,7 +582,8 @@ u16 capi20_isinstalled(void) { int i; for (i = 0; i < CAPI_MAXCONTR; i++) { - if (capi_cards[i] && capi_cards[i]->cardstate == CARD_RUNNING) + if (capi_controller[i] && + capi_controller[i]->state == CAPI_CTR_RUNNING) return CAPI_NOERROR; } return CAPI_REGNOTINSTALLED; @@ -635,9 +642,10 @@ u16 capi20_register(struct capi20_appl *ap) mutex_lock(&controller_mutex); for (i = 0; i < CAPI_MAXCONTR; i++) { - if (!capi_cards[i] || capi_cards[i]->cardstate != CARD_RUNNING) + if (!capi_controller[i] || + capi_controller[i]->state != CAPI_CTR_RUNNING) continue; - register_appl(capi_cards[i], applid, &ap->rparam); + register_appl(capi_controller[i], applid, &ap->rparam); } mutex_unlock(&controller_mutex); @@ -674,9 +682,10 @@ u16 capi20_release(struct capi20_appl *ap) mutex_lock(&controller_mutex); for (i = 0; i < CAPI_MAXCONTR; i++) { - if (!capi_cards[i] || capi_cards[i]->cardstate != CARD_RUNNING) + if (!capi_controller[i] || + capi_controller[i]->state != CAPI_CTR_RUNNING) continue; - release_appl(capi_cards[i], ap->applid); + release_appl(capi_controller[i], ap->applid); } mutex_unlock(&controller_mutex); @@ -703,13 +712,13 @@ EXPORT_SYMBOL(capi20_release); u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) { - struct capi_ctr *card; + struct capi_ctr *ctr; int showctl = 0; u8 cmd, subcmd; DBG("applid %#x", ap->applid); - if (ncards == 0) + if (ncontrollers == 0) return CAPI_REGNOTINSTALLED; if ((ap->applid == 0) || ap->release_in_progress) return CAPI_ILLAPPNR; @@ -717,28 +726,30 @@ u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data)) || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data))) return CAPI_ILLCMDORSUBCMDORMSGTOSMALL; - card = get_capi_ctr_by_nr(CAPIMSG_CONTROLLER(skb->data)); - if (!card || card->cardstate != CARD_RUNNING) { - card = get_capi_ctr_by_nr(1); // XXX why? - if (!card || card->cardstate != CARD_RUNNING) + ctr = get_capi_ctr_by_nr(CAPIMSG_CONTROLLER(skb->data)); + if (!ctr || ctr->state != CAPI_CTR_RUNNING) { + ctr = get_capi_ctr_by_nr(1); /* XXX why? */ + if (!ctr || ctr->state != CAPI_CTR_RUNNING) return CAPI_REGNOTINSTALLED; } - if (card->blocked) + if (ctr->blocked) return CAPI_SENDQUEUEFULL; cmd = CAPIMSG_COMMAND(skb->data); subcmd = CAPIMSG_SUBCOMMAND(skb->data); if (cmd == CAPI_DATA_B3 && subcmd== CAPI_REQ) { - card->nsentdatapkt++; + ctr->nsentdatapkt++; ap->nsentdatapkt++; - if (card->traceflag > 2) showctl |= 2; + if (ctr->traceflag > 2) + showctl |= 2; } else { - card->nsentctlpkt++; + ctr->nsentctlpkt++; ap->nsentctlpkt++; - if (card->traceflag) showctl |= 2; + if (ctr->traceflag) + showctl |= 2; } - showctl |= (card->traceflag & 1); + showctl |= (ctr->traceflag & 1); if (showctl & 2) { if (showctl & 1) { printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u\n", @@ -761,7 +772,7 @@ u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) CAPIMSG_LEN(skb->data)); } } - return card->send_message(card, skb); + return ctr->send_message(ctr, skb); } EXPORT_SYMBOL(capi20_put_message); @@ -778,16 +789,16 @@ EXPORT_SYMBOL(capi20_put_message); u16 capi20_get_manufacturer(u32 contr, u8 *buf) { - struct capi_ctr *card; + struct capi_ctr *ctr; if (contr == 0) { strlcpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN); return CAPI_NOERROR; } - card = get_capi_ctr_by_nr(contr); - if (!card || card->cardstate != CARD_RUNNING) + ctr = get_capi_ctr_by_nr(contr); + if (!ctr || ctr->state != CAPI_CTR_RUNNING) return CAPI_REGNOTINSTALLED; - strlcpy(buf, card->manu, CAPI_MANUFACTURER_LEN); + strlcpy(buf, ctr->manu, CAPI_MANUFACTURER_LEN); return CAPI_NOERROR; } @@ -805,17 +816,17 @@ EXPORT_SYMBOL(capi20_get_manufacturer); u16 capi20_get_version(u32 contr, struct capi_version *verp) { - struct capi_ctr *card; + struct capi_ctr *ctr; if (contr == 0) { *verp = driver_version; return CAPI_NOERROR; } - card = get_capi_ctr_by_nr(contr); - if (!card || card->cardstate != CARD_RUNNING) + ctr = get_capi_ctr_by_nr(contr); + if (!ctr || ctr->state != CAPI_CTR_RUNNING) return CAPI_REGNOTINSTALLED; - memcpy((void *) verp, &card->version, sizeof(capi_version)); + memcpy(verp, &ctr->version, sizeof(capi_version)); return CAPI_NOERROR; } @@ -833,17 +844,17 @@ EXPORT_SYMBOL(capi20_get_version); u16 capi20_get_serial(u32 contr, u8 *serial) { - struct capi_ctr *card; + struct capi_ctr *ctr; if (contr == 0) { strlcpy(serial, driver_serial, CAPI_SERIAL_LEN); return CAPI_NOERROR; } - card = get_capi_ctr_by_nr(contr); - if (!card || card->cardstate != CARD_RUNNING) + ctr = get_capi_ctr_by_nr(contr); + if (!ctr || ctr->state != CAPI_CTR_RUNNING) return CAPI_REGNOTINSTALLED; - strlcpy((void *) serial, card->serial, CAPI_SERIAL_LEN); + strlcpy(serial, ctr->serial, CAPI_SERIAL_LEN); return CAPI_NOERROR; } @@ -861,18 +872,17 @@ EXPORT_SYMBOL(capi20_get_serial); u16 capi20_get_profile(u32 contr, struct capi_profile *profp) { - struct capi_ctr *card; + struct capi_ctr *ctr; if (contr == 0) { - profp->ncontroller = ncards; + profp->ncontroller = ncontrollers; return CAPI_NOERROR; } - card = get_capi_ctr_by_nr(contr); - if (!card || card->cardstate != CARD_RUNNING) + ctr = get_capi_ctr_by_nr(contr); + if (!ctr || ctr->state != CAPI_CTR_RUNNING) return CAPI_REGNOTINSTALLED; - memcpy((void *) profp, &card->profile, - sizeof(struct capi_profile)); + memcpy(profp, &ctr->profile, sizeof(struct capi_profile)); return CAPI_NOERROR; } @@ -885,7 +895,7 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) avmb1_extcarddef cdef; avmb1_resetdef rdef; capicardparams cparams; - struct capi_ctr *card; + struct capi_ctr *ctr; struct capi_driver *driver = NULL; capiloaddata ldata; struct list_head *l; @@ -958,26 +968,26 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) sizeof(avmb1_loadandconfigdef))) return -EFAULT; } - card = get_capi_ctr_by_nr(ldef.contr); - if (!card) + ctr = get_capi_ctr_by_nr(ldef.contr); + if (!ctr) return -EINVAL; - card = capi_ctr_get(card); - if (!card) + ctr = capi_ctr_get(ctr); + if (!ctr) return -ESRCH; - if (card->load_firmware == NULL) { + if (ctr->load_firmware == NULL) { printk(KERN_DEBUG "kcapi: load: no load function\n"); - capi_ctr_put(card); + capi_ctr_put(ctr); return -ESRCH; } if (ldef.t4file.len <= 0) { printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len); - capi_ctr_put(card); + capi_ctr_put(ctr); return -EINVAL; } if (ldef.t4file.data == NULL) { printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n"); - capi_ctr_put(card); + capi_ctr_put(ctr); return -EINVAL; } @@ -988,46 +998,46 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) ldata.configuration.data = ldef.t4config.data; ldata.configuration.len = ldef.t4config.len; - if (card->cardstate != CARD_DETECTED) { + if (ctr->state != CAPI_CTR_DETECTED) { printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr); - capi_ctr_put(card); + capi_ctr_put(ctr); return -EBUSY; } - card->cardstate = CARD_LOADING; + ctr->state = CAPI_CTR_LOADING; - retval = card->load_firmware(card, &ldata); + retval = ctr->load_firmware(ctr, &ldata); if (retval) { - card->cardstate = CARD_DETECTED; - capi_ctr_put(card); + ctr->state = CAPI_CTR_DETECTED; + capi_ctr_put(ctr); return retval; } - while (card->cardstate != CARD_RUNNING) { + while (ctr->state != CAPI_CTR_RUNNING) { msleep_interruptible(100); /* 0.1 sec */ if (signal_pending(current)) { - capi_ctr_put(card); + capi_ctr_put(ctr); return -EINTR; } } - capi_ctr_put(card); + capi_ctr_put(ctr); return 0; case AVMB1_RESETCARD: if (copy_from_user(&rdef, data, sizeof(avmb1_resetdef))) return -EFAULT; - card = get_capi_ctr_by_nr(rdef.contr); - if (!card) + ctr = get_capi_ctr_by_nr(rdef.contr); + if (!ctr) return -ESRCH; - if (card->cardstate == CARD_DETECTED) + if (ctr->state == CAPI_CTR_DETECTED) return 0; - card->reset_ctr(card); + ctr->reset_ctr(ctr); - while (card->cardstate > CARD_DETECTED) { + while (ctr->state > CAPI_CTR_DETECTED) { msleep_interruptible(100); /* 0.1 sec */ @@ -1052,7 +1062,7 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) int capi20_manufacturer(unsigned int cmd, void __user *data) { - struct capi_ctr *card; + struct capi_ctr *ctr; switch (cmd) { #ifdef AVMB1_COMPAT @@ -1070,13 +1080,13 @@ int capi20_manufacturer(unsigned int cmd, void __user *data) if (copy_from_user(&fdef, data, sizeof(kcapi_flagdef))) return -EFAULT; - card = get_capi_ctr_by_nr(fdef.contr); - if (!card) + ctr = get_capi_ctr_by_nr(fdef.contr); + if (!ctr) return -ESRCH; - card->traceflag = fdef.flag; + ctr->traceflag = fdef.flag; printk(KERN_INFO "kcapi: contr [%03d] set trace=%d\n", - card->cnr, card->traceflag); + ctr->cnr, ctr->traceflag); return 0; } case KCAPI_CMD_ADDCARD: diff --git a/drivers/isdn/capi/kcapi.h b/drivers/isdn/capi/kcapi.h index 244711f7f838..f62c53bd6a97 100644 --- a/drivers/isdn/capi/kcapi.h +++ b/drivers/isdn/capi/kcapi.h @@ -24,16 +24,16 @@ printk(KERN_DEBUG "%s: " format "\n" , __func__ , ## arg); \ #endif enum { - CARD_DETECTED = 1, - CARD_LOADING = 2, - CARD_RUNNING = 3, + CAPI_CTR_DETECTED = 1, + CAPI_CTR_LOADING = 2, + CAPI_CTR_RUNNING = 3, }; extern struct list_head capi_drivers; extern rwlock_t capi_drivers_list_lock; extern struct capi20_appl *capi_applications[CAPI_MAXAPPL]; -extern struct capi_ctr *capi_cards[CAPI_MAXCONTR]; +extern struct capi_ctr *capi_controller[CAPI_MAXCONTR]; #ifdef CONFIG_PROC_FS diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c index 09d4db764d22..59fd16a4ad8e 100644 --- a/drivers/isdn/capi/kcapi_proc.c +++ b/drivers/isdn/capi/kcapi_proc.c @@ -15,13 +15,12 @@ #include #include -static char * -cardstate2str(unsigned short cardstate) +static char *state2str(unsigned short state) { - switch (cardstate) { - case CARD_DETECTED: return "detected"; - case CARD_LOADING: return "loading"; - case CARD_RUNNING: return "running"; + switch (state) { + case CAPI_CTR_DETECTED: return "detected"; + case CAPI_CTR_LOADING: return "loading"; + case CAPI_CTR_RUNNING: return "running"; default: return "???"; } } @@ -38,7 +37,7 @@ cardstate2str(unsigned short cardstate) static void *controller_start(struct seq_file *seq, loff_t *pos) { if (*pos < CAPI_MAXCONTR) - return &capi_cards[*pos]; + return &capi_controller[*pos]; return NULL; } @@ -47,7 +46,7 @@ static void *controller_next(struct seq_file *seq, void *v, loff_t *pos) { ++*pos; if (*pos < CAPI_MAXCONTR) - return &capi_cards[*pos]; + return &capi_controller[*pos]; return NULL; } @@ -65,7 +64,7 @@ static int controller_show(struct seq_file *seq, void *v) seq_printf(seq, "%d %-10s %-8s %-16s %s\n", ctr->cnr, ctr->driver_name, - cardstate2str(ctr->cardstate), + state2str(ctr->state), ctr->name, ctr->procinfo ? ctr->procinfo(ctr) : ""); -- cgit v1.2.2 From 9717fb8b64ed41be9dd074bc8010bafd33046f1a Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:11 +0000 Subject: CAPI: Convert capi drivers rwlock into mutex Turn the lock protecting registered capi drivers into a mutex and apply it consistently. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/kcapi.c | 49 +++++++++++++++++++----------------------- drivers/isdn/capi/kcapi.h | 2 +- drivers/isdn/capi/kcapi_proc.c | 8 +++---- 3 files changed, 27 insertions(+), 32 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index f37c13b4ddc7..c46964fc17c7 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -61,7 +61,7 @@ static char capi_manufakturer[64] = "AVM Berlin"; #define NCCI2CTRL(ncci) (((ncci) >> 24) & 0x7f) LIST_HEAD(capi_drivers); -DEFINE_RWLOCK(capi_drivers_list_lock); +DEFINE_MUTEX(capi_drivers_lock); static DEFINE_RWLOCK(application_lock); static DEFINE_MUTEX(controller_mutex); @@ -540,11 +540,9 @@ EXPORT_SYMBOL(detach_capi_ctr); void register_capi_driver(struct capi_driver *driver) { - unsigned long flags; - - write_lock_irqsave(&capi_drivers_list_lock, flags); + mutex_lock(&capi_drivers_lock); list_add_tail(&driver->list, &capi_drivers); - write_unlock_irqrestore(&capi_drivers_list_lock, flags); + mutex_unlock(&capi_drivers_lock); } EXPORT_SYMBOL(register_capi_driver); @@ -558,11 +556,9 @@ EXPORT_SYMBOL(register_capi_driver); void unregister_capi_driver(struct capi_driver *driver) { - unsigned long flags; - - write_lock_irqsave(&capi_drivers_list_lock, flags); + mutex_lock(&capi_drivers_lock); list_del(&driver->list); - write_unlock_irqrestore(&capi_drivers_list_lock, flags); + mutex_unlock(&capi_drivers_lock); } EXPORT_SYMBOL(unregister_capi_driver); @@ -899,7 +895,6 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) struct capi_driver *driver = NULL; capiloaddata ldata; struct list_head *l; - unsigned long flags; int retval; switch (cmd) { @@ -919,7 +914,8 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) cparams.irq = cdef.irq; cparams.cardnr = cdef.cardnr; - read_lock_irqsave(&capi_drivers_list_lock, flags); + mutex_lock(&capi_drivers_lock); + switch (cdef.cardtype) { case AVM_CARDTYPE_B1: list_for_each(l, &capi_drivers) { @@ -940,18 +936,15 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) break; } if (!driver) { - read_unlock_irqrestore(&capi_drivers_list_lock, flags); printk(KERN_ERR "kcapi: driver not loaded.\n"); - return -EIO; - } - if (!driver->add_card) { - read_unlock_irqrestore(&capi_drivers_list_lock, flags); + retval = -EIO; + } else if (!driver->add_card) { printk(KERN_ERR "kcapi: driver has no add card function.\n"); - return -EIO; - } + retval = -EIO; + } else + retval = driver->add_card(driver, &cparams); - retval = driver->add_card(driver, &cparams); - read_unlock_irqrestore(&capi_drivers_list_lock, flags); + mutex_unlock(&capi_drivers_lock); return retval; case AVMB1_LOAD: @@ -1107,6 +1100,8 @@ int capi20_manufacturer(unsigned int cmd, void __user *data) cparams.cardtype = 0; cdef.driver[sizeof(cdef.driver)-1] = 0; + mutex_lock(&capi_drivers_lock); + list_for_each(l, &capi_drivers) { driver = list_entry(l, struct capi_driver, list); if (strcmp(driver->name, cdef.driver) == 0) @@ -1115,15 +1110,15 @@ int capi20_manufacturer(unsigned int cmd, void __user *data) if (driver == NULL) { printk(KERN_ERR "kcapi: driver \"%s\" not loaded.\n", cdef.driver); - return -ESRCH; - } - - if (!driver->add_card) { + retval = -ESRCH; + } else if (!driver->add_card) { printk(KERN_ERR "kcapi: driver \"%s\" has no add card function.\n", cdef.driver); - return -EIO; - } + retval = -EIO; + } else + retval = driver->add_card(driver, &cparams); - return driver->add_card(driver, &cparams); + mutex_unlock(&capi_drivers_lock); + return retval; } default: diff --git a/drivers/isdn/capi/kcapi.h b/drivers/isdn/capi/kcapi.h index f62c53bd6a97..07c58500fe48 100644 --- a/drivers/isdn/capi/kcapi.h +++ b/drivers/isdn/capi/kcapi.h @@ -30,7 +30,7 @@ enum { }; extern struct list_head capi_drivers; -extern rwlock_t capi_drivers_list_lock; +extern struct mutex capi_drivers_lock; extern struct capi20_appl *capi_applications[CAPI_MAXAPPL]; extern struct capi_ctr *capi_controller[CAPI_MAXCONTR]; diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c index 59fd16a4ad8e..71b07610ff31 100644 --- a/drivers/isdn/capi/kcapi_proc.c +++ b/drivers/isdn/capi/kcapi_proc.c @@ -238,9 +238,9 @@ static const struct file_operations proc_applstats_ops = { // --------------------------------------------------------------------------- static void *capi_driver_start(struct seq_file *seq, loff_t *pos) - __acquires(&capi_drivers_list_lock) + __acquires(&capi_drivers_lock) { - read_lock(&capi_drivers_list_lock); + mutex_lock(&capi_drivers_lock); return seq_list_start(&capi_drivers, *pos); } @@ -250,9 +250,9 @@ static void *capi_driver_next(struct seq_file *seq, void *v, loff_t *pos) } static void capi_driver_stop(struct seq_file *seq, void *v) - __releases(&capi_drivers_list_lock) + __releases(&capi_drivers_lock) { - read_unlock(&capi_drivers_list_lock); + mutex_unlock(&capi_drivers_lock); } static int capi_driver_show(struct seq_file *seq, void *v) -- cgit v1.2.2 From 3efecf7a49cde47e5f2deb1d5504951ff4bede53 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:12 +0000 Subject: CAPI: Rework capi_ctr_ready/down This step prepares the application of proper controller locking: Push all state changing work into the notify handler that are called by capi_ctr_ready and capi_ctr_down, switch detach_capi_ctr to issue a synchronous ctr_down. Also ensure that we do not go through any action if the state did not change. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/kcapi.c | 95 +++++++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 45 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index c46964fc17c7..9362a7a66aa1 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -169,44 +169,74 @@ static void release_appl(struct capi_ctr *ctr, u16 applid) static void notify_up(u32 contr) { - struct capi_ctr *ctr = get_capi_ctr_by_nr(contr); struct capi20_appl *ap; + struct capi_ctr *ctr; u16 applid; - if (showcapimsgs & 1) { + if (showcapimsgs & 1) printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr); - } - if (!ctr) { + + ctr = get_capi_ctr_by_nr(contr); + if (ctr) { + if (ctr->state == CAPI_CTR_RUNNING) + return; + + ctr->state = CAPI_CTR_RUNNING; + + for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { + ap = get_capi_appl_by_nr(applid); + if (!ap || ap->release_in_progress) + continue; + register_appl(ctr, applid, &ap->rparam); + if (ap->callback && !ap->release_in_progress) + ap->callback(KCI_CONTRUP, contr, + &ctr->profile); + } + } else printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); - return; - } - for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { - ap = get_capi_appl_by_nr(applid); - if (!ap || ap->release_in_progress) continue; - register_appl(ctr, applid, &ap->rparam); - if (ap->callback && !ap->release_in_progress) - ap->callback(KCI_CONTRUP, contr, &ctr->profile); - } } /* -------- KCI_CONTRDOWN ------------------------------------- */ -static void notify_down(u32 contr) +static void ctr_down(struct capi_ctr *ctr) { struct capi20_appl *ap; u16 applid; - if (showcapimsgs & 1) { - printk(KERN_DEBUG "kcapi: notify down contr %d\n", contr); - } + if (ctr->state == CAPI_CTR_DETECTED) + return; + + ctr->state = CAPI_CTR_DETECTED; + + memset(ctr->manu, 0, sizeof(ctr->manu)); + memset(&ctr->version, 0, sizeof(ctr->version)); + memset(&ctr->profile, 0, sizeof(ctr->profile)); + memset(ctr->serial, 0, sizeof(ctr->serial)); for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { ap = get_capi_appl_by_nr(applid); - if (ap && ap->callback && !ap->release_in_progress) - ap->callback(KCI_CONTRDOWN, contr, NULL); + if (ap && !ap->release_in_progress) { + if (ap->callback) + ap->callback(KCI_CONTRDOWN, ctr->cnr, NULL); + capi_ctr_put(ctr); + } } } +static void notify_down(u32 contr) +{ + struct capi_ctr *ctr; + + if (showcapimsgs & 1) + printk(KERN_DEBUG "kcapi: notify down contr %d\n", contr); + + ctr = get_capi_ctr_by_nr(contr); + if (ctr) + ctr_down(ctr); + else + printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); +} + static void notify_handler(struct work_struct *work) { struct capi_notifier *np = @@ -368,8 +398,6 @@ EXPORT_SYMBOL(capi_ctr_handle_message); void capi_ctr_ready(struct capi_ctr *ctr) { - ctr->state = CAPI_CTR_RUNNING; - printk(KERN_NOTICE "kcapi: controller [%03d] \"%s\" ready.\n", ctr->cnr, ctr->name); @@ -388,28 +416,6 @@ EXPORT_SYMBOL(capi_ctr_ready); void capi_ctr_down(struct capi_ctr *ctr) { - u16 appl; - - DBG(""); - - if (ctr->state == CAPI_CTR_DETECTED) - return; - - ctr->state = CAPI_CTR_DETECTED; - - memset(ctr->manu, 0, sizeof(ctr->manu)); - memset(&ctr->version, 0, sizeof(ctr->version)); - memset(&ctr->profile, 0, sizeof(ctr->profile)); - memset(ctr->serial, 0, sizeof(ctr->serial)); - - for (appl = 1; appl <= CAPI_MAXAPPL; appl++) { - struct capi20_appl *ap = get_capi_appl_by_nr(appl); - if (!ap || ap->release_in_progress) - continue; - - capi_ctr_put(ctr); - } - printk(KERN_NOTICE "kcapi: controller [%03d] down.\n", ctr->cnr); notify_push(KCI_CONTRDOWN, ctr->cnr, 0, 0); @@ -513,8 +519,7 @@ EXPORT_SYMBOL(attach_capi_ctr); int detach_capi_ctr(struct capi_ctr *ctr) { - if (ctr->state != CAPI_CTR_DETECTED) - capi_ctr_down(ctr); + ctr_down(ctr); ncontrollers--; -- cgit v1.2.2 From ef69bb2ec6036945da1d3d3f07b75253f484f693 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:13 +0000 Subject: CAPI: Rework controller state notifier Another step towards proper locking: Rework the callback provided to capidrv for controller state changes. This is so far attached to an application, which would require us to hold the corresponding lock across notification calls. But there is no direct relation between a controller up/down event and an application, so let's decouple them and provide a notifier call chain for those events instead. This notifier chain is first of all used internally. Here we request the highest priority to unsure that housekeeping work is done before any other notifications. The chain is exported via [un]register_capictr_notifier to our only user, capidrv, to replace the racy and unfixable capi20_set_callback. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capidrv.c | 22 ++++++--- drivers/isdn/capi/kcapi.c | 112 ++++++++++++++++++++------------------------ 2 files changed, 67 insertions(+), 67 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c index 7d8899ad5796..bf55ed5f38e3 100644 --- a/drivers/isdn/capi/capidrv.c +++ b/drivers/isdn/capi/capidrv.c @@ -2210,19 +2210,24 @@ static int capidrv_delcontr(u16 contr) } -static void lower_callback(unsigned int cmd, u32 contr, void *data) +static int +lower_callback(struct notifier_block *nb, unsigned long val, void *v) { + capi_profile profile; + u32 contr = (long)v; - switch (cmd) { - case KCI_CONTRUP: + switch (val) { + case CAPICTR_UP: printk(KERN_INFO "capidrv: controller %hu up\n", contr); - (void) capidrv_addcontr(contr, (capi_profile *) data); + if (capi20_get_profile(contr, &profile) == CAPI_NOERROR) + (void) capidrv_addcontr(contr, &profile); break; - case KCI_CONTRDOWN: + case CAPICTR_DOWN: printk(KERN_INFO "capidrv: controller %hu down\n", contr); (void) capidrv_delcontr(contr); break; } + return NOTIFY_OK; } /* @@ -2262,6 +2267,10 @@ static void __exit proc_exit(void) remove_proc_entry("capi/capidrv", NULL); } +static struct notifier_block capictr_nb = { + .notifier_call = lower_callback, +}; + static int __init capidrv_init(void) { capi_profile profile; @@ -2278,7 +2287,7 @@ static int __init capidrv_init(void) return -EIO; } - capi20_set_callback(&global.ap, lower_callback); + register_capictr_notifier(&capictr_nb); errcode = capi20_get_profile(0, &profile); if (errcode != CAPI_NOERROR) { @@ -2300,6 +2309,7 @@ static int __init capidrv_init(void) static void __exit capidrv_exit(void) { + unregister_capictr_notifier(&capictr_nb); capi20_release(&global.ap); proc_exit(); diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index 9362a7a66aa1..e08914d33be1 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -44,12 +44,10 @@ module_param(showcapimsgs, uint, 0); /* ------------------------------------------------------------- */ -struct capi_notifier { +struct capictr_event { struct work_struct work; - unsigned int cmd; + unsigned int type; u32 controller; - u16 applid; - u32 ncci; }; /* ------------------------------------------------------------- */ @@ -71,6 +69,8 @@ struct capi_ctr *capi_controller[CAPI_MAXCONTR]; static int ncontrollers; +static BLOCKING_NOTIFIER_HEAD(ctr_notifier_list); + /* -------- controller ref counting -------------------------------------- */ static inline struct capi_ctr * @@ -165,8 +165,6 @@ static void release_appl(struct capi_ctr *ctr, u16 applid) capi_ctr_put(ctr); } -/* -------- KCI_CONTRUP --------------------------------------- */ - static void notify_up(u32 contr) { struct capi20_appl *ap; @@ -188,16 +186,11 @@ static void notify_up(u32 contr) if (!ap || ap->release_in_progress) continue; register_appl(ctr, applid, &ap->rparam); - if (ap->callback && !ap->release_in_progress) - ap->callback(KCI_CONTRUP, contr, - &ctr->profile); } } else printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); } -/* -------- KCI_CONTRDOWN ------------------------------------- */ - static void ctr_down(struct capi_ctr *ctr) { struct capi20_appl *ap; @@ -215,11 +208,8 @@ static void ctr_down(struct capi_ctr *ctr) for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { ap = get_capi_appl_by_nr(applid); - if (ap && !ap->release_in_progress) { - if (ap->callback) - ap->callback(KCI_CONTRDOWN, ctr->cnr, NULL); + if (ap && !ap->release_in_progress) capi_ctr_put(ctr); - } } } @@ -237,45 +227,63 @@ static void notify_down(u32 contr) printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); } -static void notify_handler(struct work_struct *work) +static int +notify_handler(struct notifier_block *nb, unsigned long val, void *v) { - struct capi_notifier *np = - container_of(work, struct capi_notifier, work); + u32 contr = (long)v; - switch (np->cmd) { - case KCI_CONTRUP: - notify_up(np->controller); + switch (val) { + case CAPICTR_UP: + notify_up(contr); break; - case KCI_CONTRDOWN: - notify_down(np->controller); + case CAPICTR_DOWN: + notify_down(contr); break; } + return NOTIFY_OK; +} + +static void do_notify_work(struct work_struct *work) +{ + struct capictr_event *event = + container_of(work, struct capictr_event, work); - kfree(np); + blocking_notifier_call_chain(&ctr_notifier_list, event->type, + (void *)(long)event->controller); + kfree(event); } /* * The notifier will result in adding/deleteing of devices. Devices can * only removed in user process, not in bh. */ -static int notify_push(unsigned int cmd, u32 controller, u16 applid, u32 ncci) +static int notify_push(unsigned int event_type, u32 controller) { - struct capi_notifier *np = kmalloc(sizeof(*np), GFP_ATOMIC); + struct capictr_event *event = kmalloc(sizeof(*event), GFP_ATOMIC); - if (!np) + if (!event) return -ENOMEM; - INIT_WORK(&np->work, notify_handler); - np->cmd = cmd; - np->controller = controller; - np->applid = applid; - np->ncci = ncci; + INIT_WORK(&event->work, do_notify_work); + event->type = event_type; + event->controller = controller; - schedule_work(&np->work); + schedule_work(&event->work); return 0; } - +int register_capictr_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&ctr_notifier_list, nb); +} +EXPORT_SYMBOL_GPL(register_capictr_notifier); + +int unregister_capictr_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&ctr_notifier_list, nb); +} +EXPORT_SYMBOL_GPL(unregister_capictr_notifier); + /* -------- Receiver ------------------------------------------ */ static void recv_handler(struct work_struct *work) @@ -401,7 +409,7 @@ void capi_ctr_ready(struct capi_ctr *ctr) printk(KERN_NOTICE "kcapi: controller [%03d] \"%s\" ready.\n", ctr->cnr, ctr->name); - notify_push(KCI_CONTRUP, ctr->cnr, 0, 0); + notify_push(CAPICTR_UP, ctr->cnr); } EXPORT_SYMBOL(capi_ctr_ready); @@ -418,7 +426,7 @@ void capi_ctr_down(struct capi_ctr *ctr) { printk(KERN_NOTICE "kcapi: controller [%03d] down.\n", ctr->cnr); - notify_push(KCI_CONTRDOWN, ctr->cnr, 0, 0); + notify_push(CAPICTR_DOWN, ctr->cnr); } EXPORT_SYMBOL(capi_ctr_down); @@ -633,7 +641,6 @@ u16 capi20_register(struct capi20_appl *ap) ap->nrecvdatapkt = 0; ap->nsentctlpkt = 0; ap->nsentdatapkt = 0; - ap->callback = NULL; mutex_init(&ap->recv_mtx); skb_queue_head_init(&ap->recv_queue); INIT_WORK(&ap->recv_work, recv_handler); @@ -1137,30 +1144,6 @@ int capi20_manufacturer(unsigned int cmd, void __user *data) EXPORT_SYMBOL(capi20_manufacturer); -/* temporary hack */ - -/** - * capi20_set_callback() - set CAPI application notification callback function - * @ap: CAPI application descriptor structure. - * @callback: callback function (NULL to remove). - * - * If not NULL, the callback function will be called to notify the - * application of the addition or removal of a controller. - * The first argument (cmd) will tell whether the controller was added - * (KCI_CONTRUP) or removed (KCI_CONTRDOWN). - * The second argument (contr) will be the controller number. - * For cmd==KCI_CONTRUP the third argument (data) will be a pointer to the - * new controller's capability profile structure. - */ - -void capi20_set_callback(struct capi20_appl *ap, - void (*callback) (unsigned int cmd, __u32 contr, void *data)) -{ - ap->callback = callback; -} - -EXPORT_SYMBOL(capi20_set_callback); - /* ------------------------------------------------------------- */ /* -------- Init & Cleanup ------------------------------------- */ /* ------------------------------------------------------------- */ @@ -1169,10 +1152,17 @@ EXPORT_SYMBOL(capi20_set_callback); * init / exit functions */ +static struct notifier_block capictr_nb = { + .notifier_call = notify_handler, + .priority = INT_MAX, +}; + static int __init kcapi_init(void) { int err; + register_capictr_notifier(&capictr_nb); + err = cdebug_init(); if (!err) kcapi_proc_init(); -- cgit v1.2.2 From 0ca3a017a7373a4545dd7b345a8a0cecc16bc7e2 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:14 +0000 Subject: CAPI: Rework locking of controller data structures This patch applies the mutex so far only protecting the controller list to (almost) all accesses of controller data structures. It also reworks waiting on state changes in old_capi_manufacturer so that it no longer poll and holds a module reference to the controller owner while waiting (the latter was partly done already). Modification and checking of the blocked state remains racy by design, the caller is responsible for dealing with this. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/kcapi.c | 291 +++++++++++++++++++++++++++++------------ drivers/isdn/capi/kcapi.h | 5 +- drivers/isdn/capi/kcapi_proc.c | 5 + 3 files changed, 214 insertions(+), 87 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index e08914d33be1..a99f7e3f8f51 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -61,11 +61,12 @@ static char capi_manufakturer[64] = "AVM Berlin"; LIST_HEAD(capi_drivers); DEFINE_MUTEX(capi_drivers_lock); +struct capi_ctr *capi_controller[CAPI_MAXCONTR]; +DEFINE_MUTEX(capi_controller_lock); + static DEFINE_RWLOCK(application_lock); -static DEFINE_MUTEX(controller_mutex); struct capi20_appl *capi_applications[CAPI_MAXAPPL]; -struct capi_ctr *capi_controller[CAPI_MAXCONTR]; static int ncontrollers; @@ -171,13 +172,15 @@ static void notify_up(u32 contr) struct capi_ctr *ctr; u16 applid; + mutex_lock(&capi_controller_lock); + if (showcapimsgs & 1) printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr); ctr = get_capi_ctr_by_nr(contr); if (ctr) { if (ctr->state == CAPI_CTR_RUNNING) - return; + goto unlock_out; ctr->state = CAPI_CTR_RUNNING; @@ -187,19 +190,24 @@ static void notify_up(u32 contr) continue; register_appl(ctr, applid, &ap->rparam); } + + wake_up_interruptible_all(&ctr->state_wait_queue); } else printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); + +unlock_out: + mutex_unlock(&capi_controller_lock); } -static void ctr_down(struct capi_ctr *ctr) +static void ctr_down(struct capi_ctr *ctr, int new_state) { struct capi20_appl *ap; u16 applid; - if (ctr->state == CAPI_CTR_DETECTED) + if (ctr->state == CAPI_CTR_DETECTED || ctr->state == CAPI_CTR_DETACHED) return; - ctr->state = CAPI_CTR_DETECTED; + ctr->state = new_state; memset(ctr->manu, 0, sizeof(ctr->manu)); memset(&ctr->version, 0, sizeof(ctr->version)); @@ -211,20 +219,26 @@ static void ctr_down(struct capi_ctr *ctr) if (ap && !ap->release_in_progress) capi_ctr_put(ctr); } + + wake_up_interruptible_all(&ctr->state_wait_queue); } static void notify_down(u32 contr) { struct capi_ctr *ctr; + mutex_lock(&capi_controller_lock); + if (showcapimsgs & 1) printk(KERN_DEBUG "kcapi: notify down contr %d\n", contr); ctr = get_capi_ctr_by_nr(contr); if (ctr) - ctr_down(ctr); + ctr_down(ctr, CAPI_CTR_DETECTED); else printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); + + mutex_unlock(&capi_controller_lock); } static int @@ -436,6 +450,9 @@ EXPORT_SYMBOL(capi_ctr_down); * @ctr: controller descriptor structure. * * Called by hardware driver to stop data flow. + * + * Note: The caller is responsible for synchronizing concurrent state changes + * as well as invocations of capi_ctr_handle_message. */ void capi_ctr_suspend_output(struct capi_ctr *ctr) @@ -454,6 +471,9 @@ EXPORT_SYMBOL(capi_ctr_suspend_output); * @ctr: controller descriptor structure. * * Called by hardware driver to resume data flow. + * + * Note: The caller is responsible for synchronizing concurrent state changes + * as well as invocations of capi_ctr_handle_message. */ void capi_ctr_resume_output(struct capi_ctr *ctr) @@ -481,21 +501,19 @@ int attach_capi_ctr(struct capi_ctr *ctr) { int i; - mutex_lock(&controller_mutex); + mutex_lock(&capi_controller_lock); for (i = 0; i < CAPI_MAXCONTR; i++) { if (!capi_controller[i]) break; } if (i == CAPI_MAXCONTR) { - mutex_unlock(&controller_mutex); + mutex_unlock(&capi_controller_lock); printk(KERN_ERR "kcapi: out of controller slots\n"); return -EBUSY; } capi_controller[i] = ctr; - mutex_unlock(&controller_mutex); - ctr->nrecvctlpkt = 0; ctr->nrecvdatapkt = 0; ctr->nsentctlpkt = 0; @@ -504,11 +522,15 @@ int attach_capi_ctr(struct capi_ctr *ctr) ctr->state = CAPI_CTR_DETECTED; ctr->blocked = 0; ctr->traceflag = showcapimsgs; + init_waitqueue_head(&ctr->state_wait_queue); sprintf(ctr->procfn, "capi/controllers/%d", ctr->cnr); ctr->procent = proc_create_data(ctr->procfn, 0, NULL, ctr->proc_fops, ctr); ncontrollers++; + + mutex_unlock(&capi_controller_lock); + printk(KERN_NOTICE "kcapi: controller [%03d]: %s attached\n", ctr->cnr, ctr->name); return 0; @@ -527,19 +549,29 @@ EXPORT_SYMBOL(attach_capi_ctr); int detach_capi_ctr(struct capi_ctr *ctr) { - ctr_down(ctr); + int err = 0; - ncontrollers--; + mutex_lock(&capi_controller_lock); - if (ctr->procent) { - remove_proc_entry(ctr->procfn, NULL); - ctr->procent = NULL; + ctr_down(ctr, CAPI_CTR_DETACHED); + + if (capi_controller[ctr->cnr - 1] != ctr) { + err = -EINVAL; + goto unlock_out; } capi_controller[ctr->cnr - 1] = NULL; + ncontrollers--; + + if (ctr->procent) + remove_proc_entry(ctr->procfn, NULL); + printk(KERN_NOTICE "kcapi: controller [%03d]: %s unregistered\n", ctr->cnr, ctr->name); - return 0; +unlock_out: + mutex_unlock(&capi_controller_lock); + + return err; } EXPORT_SYMBOL(detach_capi_ctr); @@ -589,13 +621,21 @@ EXPORT_SYMBOL(unregister_capi_driver); u16 capi20_isinstalled(void) { + u16 ret = CAPI_REGNOTINSTALLED; int i; - for (i = 0; i < CAPI_MAXCONTR; i++) { + + mutex_lock(&capi_controller_lock); + + for (i = 0; i < CAPI_MAXCONTR; i++) if (capi_controller[i] && - capi_controller[i]->state == CAPI_CTR_RUNNING) - return CAPI_NOERROR; - } - return CAPI_REGNOTINSTALLED; + capi_controller[i]->state == CAPI_CTR_RUNNING) { + ret = CAPI_NOERROR; + break; + } + + mutex_unlock(&capi_controller_lock); + + return ret; } EXPORT_SYMBOL(capi20_isinstalled); @@ -648,14 +688,16 @@ u16 capi20_register(struct capi20_appl *ap) write_unlock_irqrestore(&application_lock, flags); - mutex_lock(&controller_mutex); + mutex_lock(&capi_controller_lock); + for (i = 0; i < CAPI_MAXCONTR; i++) { if (!capi_controller[i] || capi_controller[i]->state != CAPI_CTR_RUNNING) continue; register_appl(capi_controller[i], applid, &ap->rparam); } - mutex_unlock(&controller_mutex); + + mutex_unlock(&capi_controller_lock); if (showcapimsgs & 1) { printk(KERN_DEBUG "kcapi: appl %d up\n", applid); @@ -688,14 +730,16 @@ u16 capi20_release(struct capi20_appl *ap) capi_applications[ap->applid - 1] = NULL; write_unlock_irqrestore(&application_lock, flags); - mutex_lock(&controller_mutex); + mutex_lock(&capi_controller_lock); + for (i = 0; i < CAPI_MAXCONTR; i++) { if (!capi_controller[i] || capi_controller[i]->state != CAPI_CTR_RUNNING) continue; release_appl(capi_controller[i], ap->applid); } - mutex_unlock(&controller_mutex); + + mutex_unlock(&capi_controller_lock); flush_scheduled_work(); skb_queue_purge(&ap->recv_queue); @@ -734,6 +778,12 @@ u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data)) || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data))) return CAPI_ILLCMDORSUBCMDORMSGTOSMALL; + + /* + * The controller reference is protected by the existence of the + * application passed to us. We assume that the caller properly + * synchronizes this service with capi20_release. + */ ctr = get_capi_ctr_by_nr(CAPIMSG_CONTROLLER(skb->data)); if (!ctr || ctr->state != CAPI_CTR_RUNNING) { ctr = get_capi_ctr_by_nr(1); /* XXX why? */ @@ -798,16 +848,24 @@ EXPORT_SYMBOL(capi20_put_message); u16 capi20_get_manufacturer(u32 contr, u8 *buf) { struct capi_ctr *ctr; + u16 ret; if (contr == 0) { strlcpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN); return CAPI_NOERROR; } + + mutex_lock(&capi_controller_lock); + ctr = get_capi_ctr_by_nr(contr); - if (!ctr || ctr->state != CAPI_CTR_RUNNING) - return CAPI_REGNOTINSTALLED; - strlcpy(buf, ctr->manu, CAPI_MANUFACTURER_LEN); - return CAPI_NOERROR; + if (ctr && ctr->state == CAPI_CTR_RUNNING) { + strlcpy(buf, ctr->manu, CAPI_MANUFACTURER_LEN); + ret = CAPI_NOERROR; + } else + ret = CAPI_REGNOTINSTALLED; + + mutex_unlock(&capi_controller_lock); + return ret; } EXPORT_SYMBOL(capi20_get_manufacturer); @@ -825,17 +883,24 @@ EXPORT_SYMBOL(capi20_get_manufacturer); u16 capi20_get_version(u32 contr, struct capi_version *verp) { struct capi_ctr *ctr; + u16 ret; if (contr == 0) { *verp = driver_version; return CAPI_NOERROR; } + + mutex_lock(&capi_controller_lock); + ctr = get_capi_ctr_by_nr(contr); - if (!ctr || ctr->state != CAPI_CTR_RUNNING) - return CAPI_REGNOTINSTALLED; + if (ctr && ctr->state == CAPI_CTR_RUNNING) { + memcpy(verp, &ctr->version, sizeof(capi_version)); + ret = CAPI_NOERROR; + } else + ret = CAPI_REGNOTINSTALLED; - memcpy(verp, &ctr->version, sizeof(capi_version)); - return CAPI_NOERROR; + mutex_unlock(&capi_controller_lock); + return ret; } EXPORT_SYMBOL(capi20_get_version); @@ -853,17 +918,24 @@ EXPORT_SYMBOL(capi20_get_version); u16 capi20_get_serial(u32 contr, u8 *serial) { struct capi_ctr *ctr; + u16 ret; if (contr == 0) { strlcpy(serial, driver_serial, CAPI_SERIAL_LEN); return CAPI_NOERROR; } + + mutex_lock(&capi_controller_lock); + ctr = get_capi_ctr_by_nr(contr); - if (!ctr || ctr->state != CAPI_CTR_RUNNING) - return CAPI_REGNOTINSTALLED; + if (ctr && ctr->state == CAPI_CTR_RUNNING) { + strlcpy(serial, ctr->serial, CAPI_SERIAL_LEN); + ret = CAPI_NOERROR; + } else + ret = CAPI_REGNOTINSTALLED; - strlcpy(serial, ctr->serial, CAPI_SERIAL_LEN); - return CAPI_NOERROR; + mutex_unlock(&capi_controller_lock); + return ret; } EXPORT_SYMBOL(capi20_get_serial); @@ -881,21 +953,64 @@ EXPORT_SYMBOL(capi20_get_serial); u16 capi20_get_profile(u32 contr, struct capi_profile *profp) { struct capi_ctr *ctr; + u16 ret; if (contr == 0) { profp->ncontroller = ncontrollers; return CAPI_NOERROR; } + + mutex_lock(&capi_controller_lock); + ctr = get_capi_ctr_by_nr(contr); - if (!ctr || ctr->state != CAPI_CTR_RUNNING) - return CAPI_REGNOTINSTALLED; + if (ctr && ctr->state == CAPI_CTR_RUNNING) { + memcpy(profp, &ctr->profile, sizeof(struct capi_profile)); + ret = CAPI_NOERROR; + } else + ret = CAPI_REGNOTINSTALLED; - memcpy(profp, &ctr->profile, sizeof(struct capi_profile)); - return CAPI_NOERROR; + mutex_unlock(&capi_controller_lock); + return ret; } EXPORT_SYMBOL(capi20_get_profile); +/* Must be called with capi_controller_lock held. */ +static int wait_on_ctr_state(struct capi_ctr *ctr, unsigned int state) +{ + DEFINE_WAIT(wait); + int retval = 0; + + ctr = capi_ctr_get(ctr); + if (!ctr) + return -ESRCH; + + for (;;) { + prepare_to_wait(&ctr->state_wait_queue, &wait, + TASK_INTERRUPTIBLE); + + if (ctr->state == state) + break; + if (ctr->state == CAPI_CTR_DETACHED) { + retval = -ESRCH; + break; + } + if (signal_pending(current)) { + retval = -EINTR; + break; + } + + mutex_unlock(&capi_controller_lock); + schedule(); + mutex_lock(&capi_controller_lock); + } + finish_wait(&ctr->state_wait_queue, &wait); + + capi_ctr_put(ctr); + + return retval; +} + #ifdef AVMB1_COMPAT static int old_capi_manufacturer(unsigned int cmd, void __user *data) { @@ -973,27 +1088,30 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) sizeof(avmb1_loadandconfigdef))) return -EFAULT; } + + mutex_lock(&capi_controller_lock); + ctr = get_capi_ctr_by_nr(ldef.contr); - if (!ctr) - return -EINVAL; - ctr = capi_ctr_get(ctr); - if (!ctr) - return -ESRCH; + if (!ctr) { + retval = -EINVAL; + goto load_unlock_out; + } + if (ctr->load_firmware == NULL) { printk(KERN_DEBUG "kcapi: load: no load function\n"); - capi_ctr_put(ctr); - return -ESRCH; + retval = -ESRCH; + goto load_unlock_out; } if (ldef.t4file.len <= 0) { printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len); - capi_ctr_put(ctr); - return -EINVAL; + retval = -EINVAL; + goto load_unlock_out; } if (ldef.t4file.data == NULL) { printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n"); - capi_ctr_put(ctr); - return -EINVAL; + retval = -EINVAL; + goto load_unlock_out; } ldata.firmware.user = 1; @@ -1005,52 +1123,47 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) if (ctr->state != CAPI_CTR_DETECTED) { printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr); - capi_ctr_put(ctr); - return -EBUSY; + retval = -EBUSY; + goto load_unlock_out; } ctr->state = CAPI_CTR_LOADING; retval = ctr->load_firmware(ctr, &ldata); - if (retval) { ctr->state = CAPI_CTR_DETECTED; - capi_ctr_put(ctr); - return retval; + goto load_unlock_out; } - while (ctr->state != CAPI_CTR_RUNNING) { - - msleep_interruptible(100); /* 0.1 sec */ + retval = wait_on_ctr_state(ctr, CAPI_CTR_RUNNING); - if (signal_pending(current)) { - capi_ctr_put(ctr); - return -EINTR; - } - } - capi_ctr_put(ctr); - return 0; +load_unlock_out: + mutex_unlock(&capi_controller_lock); + return retval; case AVMB1_RESETCARD: if (copy_from_user(&rdef, data, sizeof(avmb1_resetdef))) return -EFAULT; + + retval = 0; + + mutex_lock(&capi_controller_lock); + ctr = get_capi_ctr_by_nr(rdef.contr); - if (!ctr) - return -ESRCH; + if (!ctr) { + retval = -ESRCH; + goto reset_unlock_out; + } if (ctr->state == CAPI_CTR_DETECTED) - return 0; + goto reset_unlock_out; ctr->reset_ctr(ctr); - while (ctr->state > CAPI_CTR_DETECTED) { - - msleep_interruptible(100); /* 0.1 sec */ - - if (signal_pending(current)) - return -EINTR; - } - return 0; + retval = wait_on_ctr_state(ctr, CAPI_CTR_DETECTED); +reset_unlock_out: + mutex_unlock(&capi_controller_lock); + return retval; } return -EINVAL; } @@ -1068,6 +1181,7 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) int capi20_manufacturer(unsigned int cmd, void __user *data) { struct capi_ctr *ctr; + int retval; switch (cmd) { #ifdef AVMB1_COMPAT @@ -1085,14 +1199,20 @@ int capi20_manufacturer(unsigned int cmd, void __user *data) if (copy_from_user(&fdef, data, sizeof(kcapi_flagdef))) return -EFAULT; + mutex_lock(&capi_controller_lock); + ctr = get_capi_ctr_by_nr(fdef.contr); - if (!ctr) - return -ESRCH; + if (ctr) { + ctr->traceflag = fdef.flag; + printk(KERN_INFO "kcapi: contr [%03d] set trace=%d\n", + ctr->cnr, ctr->traceflag); + retval = 0; + } else + retval = -ESRCH; + + mutex_unlock(&capi_controller_lock); - ctr->traceflag = fdef.flag; - printk(KERN_INFO "kcapi: contr [%03d] set trace=%d\n", - ctr->cnr, ctr->traceflag); - return 0; + return retval; } case KCAPI_CMD_ADDCARD: { @@ -1100,7 +1220,6 @@ int capi20_manufacturer(unsigned int cmd, void __user *data) struct capi_driver *driver = NULL; capicardparams cparams; kcapi_carddef cdef; - int retval; if ((retval = copy_from_user(&cdef, data, sizeof(cdef)))) return retval; diff --git a/drivers/isdn/capi/kcapi.h b/drivers/isdn/capi/kcapi.h index 07c58500fe48..f4620b38ec51 100644 --- a/drivers/isdn/capi/kcapi.h +++ b/drivers/isdn/capi/kcapi.h @@ -24,6 +24,7 @@ printk(KERN_DEBUG "%s: " format "\n" , __func__ , ## arg); \ #endif enum { + CAPI_CTR_DETACHED = 0, CAPI_CTR_DETECTED = 1, CAPI_CTR_LOADING = 2, CAPI_CTR_RUNNING = 3, @@ -32,8 +33,10 @@ enum { extern struct list_head capi_drivers; extern struct mutex capi_drivers_lock; -extern struct capi20_appl *capi_applications[CAPI_MAXAPPL]; extern struct capi_ctr *capi_controller[CAPI_MAXCONTR]; +extern struct mutex capi_controller_lock; + +extern struct capi20_appl *capi_applications[CAPI_MAXAPPL]; #ifdef CONFIG_PROC_FS diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c index 71b07610ff31..3e6e17a24389 100644 --- a/drivers/isdn/capi/kcapi_proc.c +++ b/drivers/isdn/capi/kcapi_proc.c @@ -35,7 +35,10 @@ static char *state2str(unsigned short state) // --------------------------------------------------------------------------- static void *controller_start(struct seq_file *seq, loff_t *pos) + __acquires(capi_controller_lock) { + mutex_lock(&capi_controller_lock); + if (*pos < CAPI_MAXCONTR) return &capi_controller[*pos]; @@ -52,7 +55,9 @@ static void *controller_next(struct seq_file *seq, void *v, loff_t *pos) } static void controller_stop(struct seq_file *seq, void *v) + __releases(capi_controller_lock) { + mutex_unlock(&capi_controller_lock); } static int controller_show(struct seq_file *seq, void *v) -- cgit v1.2.2 From 88c896ef87fd0dd4dbf36e8e86e019c74b1f6649 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:15 +0000 Subject: CAPI: Rework application locking Drop the application rw-lock in favour of RCU. This synchronizes capi20_release against capi_ctr_handle_message which may dereference an application from (soft-)IRQ context. Any other access to the application list is now protected by the capi_controller_lock as well. This also allows to safely inspect applications for /proc dumping by holding capi_controller_lock. At this chance, drop some useless release_in_progress checks where we obtained the application pointer from the list (which becomes NULL on release_in_progress). Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/kcapi.c | 52 ++++++++++++++++++------------------------ drivers/isdn/capi/kcapi_proc.c | 11 +++++---- 2 files changed, 29 insertions(+), 34 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index a99f7e3f8f51..0b4c8a7396bc 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -34,6 +34,7 @@ #include #endif #include +#include static int showcapimsgs = 0; @@ -64,8 +65,6 @@ DEFINE_MUTEX(capi_drivers_lock); struct capi_ctr *capi_controller[CAPI_MAXCONTR]; DEFINE_MUTEX(capi_controller_lock); -static DEFINE_RWLOCK(application_lock); - struct capi20_appl *capi_applications[CAPI_MAXAPPL]; static int ncontrollers; @@ -103,7 +102,7 @@ static inline struct capi20_appl *get_capi_appl_by_nr(u16 applid) if (applid - 1 >= CAPI_MAXAPPL) return NULL; - return capi_applications[applid - 1]; + return rcu_dereference(capi_applications[applid - 1]); } /* -------- util functions ------------------------------------ */ @@ -186,7 +185,7 @@ static void notify_up(u32 contr) for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { ap = get_capi_appl_by_nr(applid); - if (!ap || ap->release_in_progress) + if (!ap) continue; register_appl(ctr, applid, &ap->rparam); } @@ -216,7 +215,7 @@ static void ctr_down(struct capi_ctr *ctr, int new_state) for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { ap = get_capi_appl_by_nr(applid); - if (ap && !ap->release_in_progress) + if (ap) capi_ctr_put(ctr); } @@ -336,7 +335,6 @@ void capi_ctr_handle_message(struct capi_ctr *ctr, u16 appl, struct capi20_appl *ap; int showctl = 0; u8 cmd, subcmd; - unsigned long flags; _cdebbuf *cdb; if (ctr->state != CAPI_CTR_RUNNING) { @@ -384,10 +382,10 @@ void capi_ctr_handle_message(struct capi_ctr *ctr, u16 appl, } - read_lock_irqsave(&application_lock, flags); + rcu_read_lock(); ap = get_capi_appl_by_nr(CAPIMSG_APPID(skb->data)); - if ((!ap) || (ap->release_in_progress)) { - read_unlock_irqrestore(&application_lock, flags); + if (!ap) { + rcu_read_unlock(); cdb = capi_message2str(skb->data); if (cdb) { printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s)\n", @@ -401,7 +399,7 @@ void capi_ctr_handle_message(struct capi_ctr *ctr, u16 appl, } skb_queue_tail(&ap->recv_queue, skb); schedule_work(&ap->recv_work); - read_unlock_irqrestore(&application_lock, flags); + rcu_read_unlock(); return; @@ -656,40 +654,35 @@ u16 capi20_register(struct capi20_appl *ap) { int i; u16 applid; - unsigned long flags; DBG(""); if (ap->rparam.datablklen < 128) return CAPI_LOGBLKSIZETOSMALL; - write_lock_irqsave(&application_lock, flags); + ap->nrecvctlpkt = 0; + ap->nrecvdatapkt = 0; + ap->nsentctlpkt = 0; + ap->nsentdatapkt = 0; + mutex_init(&ap->recv_mtx); + skb_queue_head_init(&ap->recv_queue); + INIT_WORK(&ap->recv_work, recv_handler); + ap->release_in_progress = 0; + + mutex_lock(&capi_controller_lock); for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { if (capi_applications[applid - 1] == NULL) break; } if (applid > CAPI_MAXAPPL) { - write_unlock_irqrestore(&application_lock, flags); + mutex_unlock(&capi_controller_lock); return CAPI_TOOMANYAPPLS; } ap->applid = applid; capi_applications[applid - 1] = ap; - ap->nrecvctlpkt = 0; - ap->nrecvdatapkt = 0; - ap->nsentctlpkt = 0; - ap->nsentdatapkt = 0; - mutex_init(&ap->recv_mtx); - skb_queue_head_init(&ap->recv_queue); - INIT_WORK(&ap->recv_work, recv_handler); - ap->release_in_progress = 0; - - write_unlock_irqrestore(&application_lock, flags); - - mutex_lock(&capi_controller_lock); - for (i = 0; i < CAPI_MAXCONTR; i++) { if (!capi_controller[i] || capi_controller[i]->state != CAPI_CTR_RUNNING) @@ -721,16 +714,15 @@ EXPORT_SYMBOL(capi20_register); u16 capi20_release(struct capi20_appl *ap) { int i; - unsigned long flags; DBG("applid %#x", ap->applid); - write_lock_irqsave(&application_lock, flags); + mutex_lock(&capi_controller_lock); + ap->release_in_progress = 1; capi_applications[ap->applid - 1] = NULL; - write_unlock_irqrestore(&application_lock, flags); - mutex_lock(&capi_controller_lock); + synchronize_rcu(); for (i = 0; i < CAPI_MAXCONTR; i++) { if (!capi_controller[i] || diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c index 3e6e17a24389..ea2dff602e49 100644 --- a/drivers/isdn/capi/kcapi_proc.c +++ b/drivers/isdn/capi/kcapi_proc.c @@ -139,9 +139,11 @@ static const struct file_operations proc_contrstats_ops = { // applid nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt // --------------------------------------------------------------------------- -static void * -applications_start(struct seq_file *seq, loff_t *pos) +static void *applications_start(struct seq_file *seq, loff_t *pos) + __acquires(capi_controller_lock) { + mutex_lock(&capi_controller_lock); + if (*pos < CAPI_MAXAPPL) return &capi_applications[*pos]; @@ -158,9 +160,10 @@ applications_next(struct seq_file *seq, void *v, loff_t *pos) return NULL; } -static void -applications_stop(struct seq_file *seq, void *v) +static void applications_stop(struct seq_file *seq, void *v) + __releases(capi_controller_lock) { + mutex_unlock(&capi_controller_lock); } static int -- cgit v1.2.2 From 501c87a91909efaad91425635b29b01f1473c659 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:16 +0000 Subject: CAPI: Reduce #ifdef mess around CONFIG_ISDN_CAPI_MIDDLEWARE Make the code a bit more readable be providing stub functions for the !CONFIG_ISDN_CAPI_MIDDLEWARE case. Though a few lines are moved around, this comes with no functional changes. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 150 ++++++++++++++++++++++++++--------------------- 1 file changed, 83 insertions(+), 67 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 3b077978c496..7d2ca6b2564c 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -23,14 +23,10 @@ #include #include #include -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE #include -#ifdef CONFIG_PPP #include #include #include -#endif /* CONFIG_PPP */ -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ #include #include #include @@ -56,17 +52,17 @@ MODULE_LICENSE("GPL"); /* -------- driver information -------------------------------------- */ static struct class *capi_class; - static int capi_major = 68; /* allocated */ + +module_param_named(major, capi_major, uint, 0); + #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE -#define CAPINC_NR_PORTS 32 +#define CAPINC_NR_PORTS 32 #define CAPINC_MAX_PORTS 256 + static int capi_ttymajor = 191; static int capi_ttyminors = CAPINC_NR_PORTS; -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ -module_param_named(major, capi_major, uint, 0); -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE module_param_named(ttymajor, capi_ttymajor, uint, 0); module_param_named(ttyminors, capi_ttyminors, uint, 0); #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ @@ -81,7 +77,6 @@ module_param_named(ttyminors, capi_ttyminors, uint, 0); struct capidev; struct capincci; -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE struct capiminor; struct datahandle_queue { @@ -116,7 +111,6 @@ struct capiminor { int nack; spinlock_t ackqlock; }; -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ /* FIXME: The following lock is a sledgehammer-workaround to a * locking issue with the capiminor (and maybe other) data structure(s). @@ -156,14 +150,13 @@ static DEFINE_RWLOCK(capidev_list_lock); static LIST_HEAD(capidev_list); #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE + static DEFINE_RWLOCK(capiminor_list_lock); static LIST_HEAD(capiminor_list); -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE /* -------- datahandles --------------------------------------------- */ -static int capincci_add_ack(struct capiminor *mp, u16 datahandle) +static int capiminor_add_ack(struct capiminor *mp, u16 datahandle) { struct datahandle_queue *n; unsigned long flags; @@ -301,26 +294,17 @@ static struct capiminor *capiminor_find(unsigned int minor) return p; } -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ /* -------- struct capincci ----------------------------------------- */ -static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci) +static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np) { - struct capincci *np, **pp; -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - struct capiminor *mp = NULL; -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ + struct capiminor *mp; - np = kzalloc(sizeof(*np), GFP_ATOMIC); - if (!np) - return NULL; - np->ncci = ncci; - np->cdev = cdev; -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - mp = NULL; - if (cdev->userflags & CAPIFLAG_HIGHJACKING) - mp = np->minorp = capiminor_alloc(&cdev->ap, ncci); + if (!(cdev->userflags & CAPIFLAG_HIGHJACKING)) + return; + + mp = np->minorp = capiminor_alloc(&cdev->ap, np->ncci); if (mp) { mp->nccip = np; #ifdef _DEBUG_REFCOUNT @@ -330,7 +314,58 @@ static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci) capifs_new_ncci(mp->minor, MKDEV(capi_ttymajor, mp->minor)); } -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ +} + +static void capincci_free_minor(struct capincci *np) +{ + struct capiminor *mp = np->minorp; + + if (mp) { + capifs_free_ncci(mp->capifs_dentry); + if (mp->tty) { + mp->nccip = NULL; +#ifdef _DEBUG_REFCOUNT + printk(KERN_DEBUG "reset mp->nccip\n"); +#endif + tty_hangup(mp->tty); + } else { + capiminor_free(mp); + } + } +} + +static inline unsigned int capincci_minor_opencount(struct capincci *np) +{ + struct capiminor *mp = np->minorp; + + return mp ? atomic_read(&mp->ttyopencount) : 0; +} + +#else /* !CONFIG_ISDN_CAPI_MIDDLEWARE */ + +static inline void +capincci_alloc_minor(struct capidev *cdev, struct capincci *np) { } +static inline void capincci_free_minor(struct capincci *np) { } + +static inline unsigned int capincci_minor_opencount(struct capincci *np) +{ + return 0; +} + +#endif /* !CONFIG_ISDN_CAPI_MIDDLEWARE */ + +static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci) +{ + struct capincci *np, **pp; + + np = kzalloc(sizeof(*np), GFP_ATOMIC); + if (!np) + return NULL; + np->ncci = ncci; + np->cdev = cdev; + + capincci_alloc_minor(cdev, np); + for (pp=&cdev->nccis; *pp; pp = &(*pp)->next) ; *pp = np; @@ -340,29 +375,13 @@ static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci) static void capincci_free(struct capidev *cdev, u32 ncci) { struct capincci *np, **pp; -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - struct capiminor *mp; -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ pp=&cdev->nccis; while (*pp) { np = *pp; if (ncci == 0xffffffff || np->ncci == ncci) { *pp = (*pp)->next; -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - if ((mp = np->minorp) != NULL) { - capifs_free_ncci(mp->capifs_dentry); - if (mp->tty) { - mp->nccip = NULL; -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "reset mp->nccip\n"); -#endif - tty_hangup(mp->tty); - } else { - capiminor_free(mp); - } - } -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ + capincci_free_minor(np); kfree(np); if (*pp == NULL) return; } else { @@ -552,7 +571,7 @@ static int handle_minor_send(struct capiminor *mp) capimsg_setu16(skb->data, 18, datahandle); capimsg_setu16(skb->data, 20, 0); /* Flags */ - if (capincci_add_ack(mp, datahandle) < 0) { + if (capiminor_add_ack(mp, datahandle) < 0) { skb_pull(skb, CAPI_DATA_B3_REQ_LEN); skb_queue_head(&mp->outqueue, skb); return count; @@ -628,10 +647,13 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) spin_unlock_irqrestore(&workaround_lock, flags); return; } + #ifndef CONFIG_ISDN_CAPI_MIDDLEWARE skb_queue_tail(&cdev->recvqueue, skb); wake_up_interruptible(&cdev->recvwait); + #else /* CONFIG_ISDN_CAPI_MIDDLEWARE */ + mp = np->minorp; if (!mp) { skb_queue_tail(&cdev->recvqueue, skb); @@ -639,10 +661,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) spin_unlock_irqrestore(&workaround_lock, flags); return; } - - if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) { - datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+4+2); #ifdef _DEBUG_DATAFLOW printk(KERN_DEBUG "capi_signal: DATA_B3_IND %u len=%d\n", @@ -672,6 +691,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) wake_up_interruptible(&cdev->recvwait); } #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ + spin_unlock_irqrestore(&workaround_lock, flags); } @@ -929,9 +949,6 @@ capi_ioctl(struct inode *inode, struct file *file, case CAPI_NCCI_OPENCOUNT: { struct capincci *nccip; -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - struct capiminor *mp; -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ unsigned ncci; int count = 0; if (copy_from_user(&ncci, argp, sizeof(ncci))) @@ -942,11 +959,7 @@ capi_ioctl(struct inode *inode, struct file *file, mutex_unlock(&cdev->ncci_list_mtx); return 0; } -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - if ((mp = nccip->minorp) != NULL) { - count += atomic_read(&mp->ttyopencount); - } -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ + count += capincci_minor_opencount(nccip); mutex_unlock(&cdev->ncci_list_mtx); return count; } @@ -1396,7 +1409,16 @@ static void capinc_tty_exit(void) put_tty_driver(drv); } -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ +#else /* !CONFIG_ISDN_CAPI_MIDDLEWARE */ + +static inline int capinc_tty_init(void) +{ + return 0; +} + +static inline void capinc_tty_exit(void) { } + +#endif /* !CONFIG_ISDN_CAPI_MIDDLEWARE */ /* -------- /proc functions ----------------------------------------- */ @@ -1505,23 +1527,19 @@ static int __init capi_init(void) device_create(capi_class, NULL, MKDEV(capi_major, 0), NULL, "capi"); -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE if (capinc_tty_init() < 0) { device_destroy(capi_class, MKDEV(capi_major, 0)); class_destroy(capi_class); unregister_chrdev(capi_major, "capi20"); return -ENOMEM; } -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ proc_init(); -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) compileinfo = " (middleware+capifs)"; -#else +#elif defined(CONFIG_ISDN_CAPI_MIDDLEWARE) compileinfo = " (no capifs)"; -#endif #else compileinfo = " (no middleware)"; #endif @@ -1539,9 +1557,7 @@ static void __exit capi_exit(void) class_destroy(capi_class); unregister_chrdev(capi_major, "capi20"); -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE capinc_tty_exit(); -#endif } module_init(capi_init); -- cgit v1.2.2 From b8f433dc5cd9b910c12ef5cca351bf720d3e68c1 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:17 +0000 Subject: CAPI: Convert capidev_list_lock into a mutex No need for anything "harder" here (specifically no need for irqsave...). Also, make the list removal the first operation of capidev_free to avoid dumping half-released devices via /proc. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 7d2ca6b2564c..623412e22c14 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -146,7 +146,7 @@ struct capidev { /* -------- global variables ---------------------------------------- */ -static DEFINE_RWLOCK(capidev_list_lock); +static DEFINE_MUTEX(capidev_list_lock); static LIST_HEAD(capidev_list); #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE @@ -406,7 +406,6 @@ static struct capincci *capincci_find(struct capidev *cdev, u32 ncci) static struct capidev *capidev_alloc(void) { struct capidev *cdev; - unsigned long flags; cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); if (!cdev) @@ -415,15 +414,19 @@ static struct capidev *capidev_alloc(void) mutex_init(&cdev->ncci_list_mtx); skb_queue_head_init(&cdev->recvqueue); init_waitqueue_head(&cdev->recvwait); - write_lock_irqsave(&capidev_list_lock, flags); + + mutex_lock(&capidev_list_lock); list_add_tail(&cdev->list, &capidev_list); - write_unlock_irqrestore(&capidev_list_lock, flags); + mutex_unlock(&capidev_list_lock); + return cdev; } static void capidev_free(struct capidev *cdev) { - unsigned long flags; + mutex_lock(&capidev_list_lock); + list_del(&cdev->list); + mutex_unlock(&capidev_list_lock); if (cdev->ap.applid) { capi20_release(&cdev->ap); @@ -435,9 +438,6 @@ static void capidev_free(struct capidev *cdev) capincci_free(cdev, 0xffffffff); mutex_unlock(&cdev->ncci_list_mtx); - write_lock_irqsave(&capidev_list_lock, flags); - list_del(&cdev->list); - write_unlock_irqrestore(&capidev_list_lock, flags); kfree(cdev); } @@ -1431,7 +1431,7 @@ static int capi20_proc_show(struct seq_file *m, void *v) struct capidev *cdev; struct list_head *l; - read_lock(&capidev_list_lock); + mutex_lock(&capidev_list_lock); list_for_each(l, &capidev_list) { cdev = list_entry(l, struct capidev, list); seq_printf(m, "0 %d %lu %lu %lu %lu\n", @@ -1441,7 +1441,7 @@ static int capi20_proc_show(struct seq_file *m, void *v) cdev->ap.nsentctlpkt, cdev->ap.nsentdatapkt); } - read_unlock(&capidev_list_lock); + mutex_unlock(&capidev_list_lock); return 0; } @@ -1468,7 +1468,7 @@ static int capi20ncci_proc_show(struct seq_file *m, void *v) struct capincci *np; struct list_head *l; - read_lock(&capidev_list_lock); + mutex_lock(&capidev_list_lock); list_for_each(l, &capidev_list) { cdev = list_entry(l, struct capidev, list); for (np=cdev->nccis; np; np = np->next) { @@ -1477,7 +1477,7 @@ static int capi20ncci_proc_show(struct seq_file *m, void *v) np->ncci); } } - read_unlock(&capidev_list_lock); + mutex_unlock(&capidev_list_lock); return 0; } -- cgit v1.2.2 From eca39dd830dbc58061aa6cd68853c39055236be3 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:18 +0000 Subject: CAPI: Clean up capi_open/release Fold capidev_alloc and capidev_free into capi_open and capi_release - there are no other users. Someone pushed a lock_kernel into capi_open. Drop it, we don't need it. Also remove the useless test from open that checks for private_data == NULL. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 93 ++++++++++++++++++------------------------------ 1 file changed, 34 insertions(+), 59 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 623412e22c14..9d7c3692c7d7 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -401,46 +401,6 @@ static struct capincci *capincci_find(struct capidev *cdev, u32 ncci) return p; } -/* -------- struct capidev ------------------------------------------ */ - -static struct capidev *capidev_alloc(void) -{ - struct capidev *cdev; - - cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); - if (!cdev) - return NULL; - - mutex_init(&cdev->ncci_list_mtx); - skb_queue_head_init(&cdev->recvqueue); - init_waitqueue_head(&cdev->recvwait); - - mutex_lock(&capidev_list_lock); - list_add_tail(&cdev->list, &capidev_list); - mutex_unlock(&capidev_list_lock); - - return cdev; -} - -static void capidev_free(struct capidev *cdev) -{ - mutex_lock(&capidev_list_lock); - list_del(&cdev->list); - mutex_unlock(&capidev_list_lock); - - if (cdev->ap.applid) { - capi20_release(&cdev->ap); - cdev->ap.applid = 0; - } - skb_queue_purge(&cdev->recvqueue); - - mutex_lock(&cdev->ncci_list_mtx); - capincci_free(cdev, 0xffffffff); - mutex_unlock(&cdev->ncci_list_mtx); - - kfree(cdev); -} - #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE /* -------- handle data queue --------------------------------------- */ @@ -991,30 +951,45 @@ capi_ioctl(struct inode *inode, struct file *file, return -EINVAL; } -static int -capi_open(struct inode *inode, struct file *file) +static int capi_open(struct inode *inode, struct file *file) { - int ret; - - lock_kernel(); - if (file->private_data) - ret = -EEXIST; - else if ((file->private_data = capidev_alloc()) == NULL) - ret = -ENOMEM; - else - ret = nonseekable_open(inode, file); - unlock_kernel(); - return ret; + struct capidev *cdev; + + cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); + if (!cdev) + return -ENOMEM; + + mutex_init(&cdev->ncci_list_mtx); + skb_queue_head_init(&cdev->recvqueue); + init_waitqueue_head(&cdev->recvwait); + file->private_data = cdev; + + mutex_lock(&capidev_list_lock); + list_add_tail(&cdev->list, &capidev_list); + mutex_unlock(&capidev_list_lock); + + return nonseekable_open(inode, file); } -static int -capi_release(struct inode *inode, struct file *file) +static int capi_release(struct inode *inode, struct file *file) { - struct capidev *cdev = (struct capidev *)file->private_data; + struct capidev *cdev = file->private_data; - capidev_free(cdev); - file->private_data = NULL; - + mutex_lock(&capidev_list_lock); + list_del(&cdev->list); + mutex_unlock(&capidev_list_lock); + + if (cdev->ap.applid) { + capi20_release(&cdev->ap); + cdev->ap.applid = 0; + } + skb_queue_purge(&cdev->recvqueue); + + mutex_lock(&cdev->ncci_list_mtx); + capincci_free(cdev, 0xffffffff); + mutex_unlock(&cdev->ncci_list_mtx); + + kfree(cdev); return 0; } -- cgit v1.2.2 From 05b4149433ffae789edaf569da8d998c93eed1aa Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:19 +0000 Subject: CAPI: Rework locking of capidev members Rename 'ncci_list_mtx' to 'lock', expressing that it now protects a larger set of capidev members: the NCCI list, ap.applid (ie. the registration of the application), and modifications of userflags. We do not need to protect each and every check for ap.applid because, once an application is registered, it will stay for the whole lifetime of the device. Also, there is no need to apply the capidev mutex during release (if there could be concurrent users, we would crash them anyway by freeing the device at the end of capi_release). Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 181 +++++++++++++++++++++++------------------------ 1 file changed, 88 insertions(+), 93 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 9d7c3692c7d7..403bf8fcb285 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -141,7 +141,7 @@ struct capidev { struct capincci *nccis; - struct mutex ncci_list_mtx; + struct mutex lock; }; /* -------- global variables ---------------------------------------- */ @@ -574,38 +574,31 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) u16 datahandle; #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ struct capincci *np; - u32 ncci; unsigned long flags; + mutex_lock(&cdev->lock); + if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_CONF) { u16 info = CAPIMSG_U16(skb->data, 12); // Info field - if ((info & 0xff00) == 0) { - mutex_lock(&cdev->ncci_list_mtx); + if ((info & 0xff00) == 0) capincci_alloc(cdev, CAPIMSG_NCCI(skb->data)); - mutex_unlock(&cdev->ncci_list_mtx); - } } - if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_IND) { - mutex_lock(&cdev->ncci_list_mtx); + if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_IND) capincci_alloc(cdev, CAPIMSG_NCCI(skb->data)); - mutex_unlock(&cdev->ncci_list_mtx); - } + spin_lock_irqsave(&workaround_lock, flags); if (CAPIMSG_COMMAND(skb->data) != CAPI_DATA_B3) { skb_queue_tail(&cdev->recvqueue, skb); wake_up_interruptible(&cdev->recvwait); - spin_unlock_irqrestore(&workaround_lock, flags); - return; + goto unlock_out; } - ncci = CAPIMSG_CONTROL(skb->data); - for (np = cdev->nccis; np && np->ncci != ncci; np = np->next) - ; + + np = capincci_find(cdev, CAPIMSG_CONTROL(skb->data)); if (!np) { printk(KERN_ERR "BUG: capi_signal: ncci not found\n"); skb_queue_tail(&cdev->recvqueue, skb); wake_up_interruptible(&cdev->recvwait); - spin_unlock_irqrestore(&workaround_lock, flags); - return; + goto unlock_out; } #ifndef CONFIG_ISDN_CAPI_MIDDLEWARE @@ -618,8 +611,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) if (!mp) { skb_queue_tail(&cdev->recvqueue, skb); wake_up_interruptible(&cdev->recvwait); - spin_unlock_irqrestore(&workaround_lock, flags); - return; + goto unlock_out; } if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) { datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+4+2); @@ -652,7 +644,9 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) } #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ +unlock_out: spin_unlock_irqrestore(&workaround_lock, flags); + mutex_unlock(&cdev->lock); } /* -------- file_operations for capidev ----------------------------- */ @@ -730,9 +724,9 @@ capi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos CAPIMSG_SETAPPID(skb->data, cdev->ap.applid); if (CAPIMSG_CMD(skb->data) == CAPI_DISCONNECT_B3_RESP) { - mutex_lock(&cdev->ncci_list_mtx); + mutex_lock(&cdev->lock); capincci_free(cdev, CAPIMSG_NCCI(skb->data)); - mutex_unlock(&cdev->ncci_list_mtx); + mutex_unlock(&cdev->lock); } cdev->errcode = capi20_put_message(&cdev->ap, skb); @@ -765,30 +759,35 @@ capi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct capidev *cdev = file->private_data; - struct capi20_appl *ap = &cdev->ap; capi_ioctl_struct data; int retval = -EINVAL; void __user *argp = (void __user *)arg; switch (cmd) { case CAPI_REGISTER: - { - if (ap->applid) - return -EEXIST; + mutex_lock(&cdev->lock); - if (copy_from_user(&cdev->ap.rparam, argp, - sizeof(struct capi_register_params))) - return -EFAULT; - - cdev->ap.private = cdev; - cdev->ap.recv_message = capi_recv_message; - cdev->errcode = capi20_register(ap); - if (cdev->errcode) { - ap->applid = 0; - return -EIO; - } + if (cdev->ap.applid) { + retval = -EEXIST; + goto register_out; + } + if (copy_from_user(&cdev->ap.rparam, argp, + sizeof(struct capi_register_params))) { + retval = -EFAULT; + goto register_out; + } + cdev->ap.private = cdev; + cdev->ap.recv_message = capi_recv_message; + cdev->errcode = capi20_register(&cdev->ap); + retval = (int)cdev->ap.applid; + if (cdev->errcode) { + cdev->ap.applid = 0; + retval = -EIO; } - return (int)ap->applid; + +register_out: + mutex_unlock(&cdev->lock); + return retval; case CAPI_GET_VERSION: { @@ -887,68 +886,67 @@ capi_ioctl(struct inode *inode, struct file *file, return 0; case CAPI_SET_FLAGS: - case CAPI_CLR_FLAGS: - { - unsigned userflags; - if (copy_from_user(&userflags, argp, - sizeof(userflags))) - return -EFAULT; - if (cmd == CAPI_SET_FLAGS) - cdev->userflags |= userflags; - else - cdev->userflags &= ~userflags; - } - return 0; + case CAPI_CLR_FLAGS: { + unsigned userflags; + + if (copy_from_user(&userflags, argp, sizeof(userflags))) + return -EFAULT; + mutex_lock(&cdev->lock); + if (cmd == CAPI_SET_FLAGS) + cdev->userflags |= userflags; + else + cdev->userflags &= ~userflags; + mutex_unlock(&cdev->lock); + return 0; + } case CAPI_GET_FLAGS: if (copy_to_user(argp, &cdev->userflags, sizeof(cdev->userflags))) return -EFAULT; return 0; - case CAPI_NCCI_OPENCOUNT: - { - struct capincci *nccip; - unsigned ncci; - int count = 0; - if (copy_from_user(&ncci, argp, sizeof(ncci))) - return -EFAULT; + case CAPI_NCCI_OPENCOUNT: { + struct capincci *nccip; + unsigned ncci; + int count = 0; - mutex_lock(&cdev->ncci_list_mtx); - if ((nccip = capincci_find(cdev, (u32) ncci)) == NULL) { - mutex_unlock(&cdev->ncci_list_mtx); - return 0; - } - count += capincci_minor_opencount(nccip); - mutex_unlock(&cdev->ncci_list_mtx); - return count; - } - return 0; + if (copy_from_user(&ncci, argp, sizeof(ncci))) + return -EFAULT; + + mutex_lock(&cdev->lock); + nccip = capincci_find(cdev, (u32)ncci); + if (nccip) + count = capincci_minor_opencount(nccip); + mutex_unlock(&cdev->lock); + return count; + } #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - case CAPI_NCCI_GETUNIT: - { - struct capincci *nccip; - struct capiminor *mp; - unsigned ncci; - int unit = 0; - if (copy_from_user(&ncci, argp, - sizeof(ncci))) - return -EFAULT; - mutex_lock(&cdev->ncci_list_mtx); - nccip = capincci_find(cdev, (u32) ncci); - if (!nccip || (mp = nccip->minorp) == NULL) { - mutex_unlock(&cdev->ncci_list_mtx); - return -ESRCH; - } - unit = mp->minor; - mutex_unlock(&cdev->ncci_list_mtx); - return unit; + case CAPI_NCCI_GETUNIT: { + struct capincci *nccip; + struct capiminor *mp; + unsigned ncci; + int unit = -ESRCH; + + if (copy_from_user(&ncci, argp, sizeof(ncci))) + return -EFAULT; + + mutex_lock(&cdev->lock); + nccip = capincci_find(cdev, (u32)ncci); + if (nccip) { + mp = nccip->minorp; + if (mp) + unit = mp->minor; } - return 0; + mutex_unlock(&cdev->lock); + return unit; + } #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ + + default: + return -EINVAL; } - return -EINVAL; } static int capi_open(struct inode *inode, struct file *file) @@ -959,7 +957,7 @@ static int capi_open(struct inode *inode, struct file *file) if (!cdev) return -ENOMEM; - mutex_init(&cdev->ncci_list_mtx); + mutex_init(&cdev->lock); skb_queue_head_init(&cdev->recvqueue); init_waitqueue_head(&cdev->recvwait); file->private_data = cdev; @@ -979,15 +977,10 @@ static int capi_release(struct inode *inode, struct file *file) list_del(&cdev->list); mutex_unlock(&capidev_list_lock); - if (cdev->ap.applid) { + if (cdev->ap.applid) capi20_release(&cdev->ap); - cdev->ap.applid = 0; - } skb_queue_purge(&cdev->recvqueue); - - mutex_lock(&cdev->ncci_list_mtx); capincci_free(cdev, 0xffffffff); - mutex_unlock(&cdev->ncci_list_mtx); kfree(cdev); return 0; @@ -1446,11 +1439,13 @@ static int capi20ncci_proc_show(struct seq_file *m, void *v) mutex_lock(&capidev_list_lock); list_for_each(l, &capidev_list) { cdev = list_entry(l, struct capidev, list); + mutex_lock(&cdev->lock); for (np=cdev->nccis; np; np = np->next) { seq_printf(m, "%d 0x%x\n", cdev->ap.applid, np->ncci); } + mutex_unlock(&cdev->lock); } mutex_unlock(&capidev_list_lock); return 0; -- cgit v1.2.2 From 54f0fad3d8414cf770c1cf25a1d98fcaec899b5a Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:20 +0000 Subject: CAPI: Use non-atomic allocation during NCCI setup Both capincci_alloc and capiminor_alloc run in non-atomic context, update their memory allocations accordingly. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 403bf8fcb285..f8f86602c57e 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -217,7 +217,7 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) unsigned int minor = 0; unsigned long flags; - mp = kzalloc(sizeof(*mp), GFP_ATOMIC); + mp = kzalloc(sizeof(*mp), GFP_KERNEL); if (!mp) { printk(KERN_ERR "capi: can't alloc capiminor\n"); return NULL; @@ -358,7 +358,7 @@ static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci) { struct capincci *np, **pp; - np = kzalloc(sizeof(*np), GFP_ATOMIC); + np = kzalloc(sizeof(*np), GFP_KERNEL); if (!np) return NULL; np->ncci = ncci; -- cgit v1.2.2 From 28a1dbb6f7feade304f43798feb15f6978516624 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:21 +0000 Subject: CAPI: Fix racy capi_read capi_read still used interruptible_sleep_on, risking to miss a wakeup this way. Convert it to wait_event_interruptible. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index f8f86602c57e..8abec9655e1a 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -657,24 +657,19 @@ capi_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) struct capidev *cdev = (struct capidev *)file->private_data; struct sk_buff *skb; size_t copied; + int err; if (!cdev->ap.applid) return -ENODEV; - if ((skb = skb_dequeue(&cdev->recvqueue)) == NULL) { - + skb = skb_dequeue(&cdev->recvqueue); + if (!skb) { if (file->f_flags & O_NONBLOCK) return -EAGAIN; - - for (;;) { - interruptible_sleep_on(&cdev->recvwait); - if ((skb = skb_dequeue(&cdev->recvqueue)) != NULL) - break; - if (signal_pending(current)) - break; - } - if (skb == NULL) - return -ERESTARTNOHAND; + err = wait_event_interruptible(cdev->recvwait, + (skb = skb_dequeue(&cdev->recvqueue))); + if (err) + return err; } if (skb->len > count) { skb_queue_head(&cdev->recvqueue, skb); -- cgit v1.2.2 From 884f5c447901ca9da75432fe8a7a2c2a00327d22 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:22 +0000 Subject: CAPI: Switch NCCI list to standard doubly linked list Replace open-coded NCCI list management with standard mechanisms. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 52 +++++++++++++++++++----------------------------- 1 file changed, 20 insertions(+), 32 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 8abec9655e1a..6704b2b004aa 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -122,7 +122,7 @@ struct capiminor { static DEFINE_SPINLOCK(workaround_lock); struct capincci { - struct capincci *next; + struct list_head list; u32 ncci; struct capidev *cdev; #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE @@ -139,7 +139,7 @@ struct capidev { struct sk_buff_head recvqueue; wait_queue_head_t recvwait; - struct capincci *nccis; + struct list_head nccis; struct mutex lock; }; @@ -356,7 +356,7 @@ static inline unsigned int capincci_minor_opencount(struct capincci *np) static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci) { - struct capincci *np, **pp; + struct capincci *np; np = kzalloc(sizeof(*np), GFP_KERNEL); if (!np) @@ -366,39 +366,31 @@ static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci) capincci_alloc_minor(cdev, np); - for (pp=&cdev->nccis; *pp; pp = &(*pp)->next) - ; - *pp = np; - return np; + list_add_tail(&np->list, &cdev->nccis); + + return np; } static void capincci_free(struct capidev *cdev, u32 ncci) { - struct capincci *np, **pp; + struct capincci *np, *tmp; - pp=&cdev->nccis; - while (*pp) { - np = *pp; + list_for_each_entry_safe(np, tmp, &cdev->nccis, list) if (ncci == 0xffffffff || np->ncci == ncci) { - *pp = (*pp)->next; capincci_free_minor(np); + list_del(&np->list); kfree(np); - if (*pp == NULL) return; - } else { - pp = &(*pp)->next; } - } } static struct capincci *capincci_find(struct capidev *cdev, u32 ncci) { - struct capincci *p; + struct capincci *np; - for (p=cdev->nccis; p ; p = p->next) { - if (p->ncci == ncci) - break; - } - return p; + list_for_each_entry(np, &cdev->nccis, list) + if (np->ncci == ncci) + return np; + return NULL; } #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE @@ -955,6 +947,7 @@ static int capi_open(struct inode *inode, struct file *file) mutex_init(&cdev->lock); skb_queue_head_init(&cdev->recvqueue); init_waitqueue_head(&cdev->recvwait); + INIT_LIST_HEAD(&cdev->nccis); file->private_data = cdev; mutex_lock(&capidev_list_lock); @@ -1427,19 +1420,14 @@ static const struct file_operations capi20_proc_fops = { */ static int capi20ncci_proc_show(struct seq_file *m, void *v) { - struct capidev *cdev; - struct capincci *np; - struct list_head *l; + struct capidev *cdev; + struct capincci *np; mutex_lock(&capidev_list_lock); - list_for_each(l, &capidev_list) { - cdev = list_entry(l, struct capidev, list); + list_for_each_entry(cdev, &capidev_list, list) { mutex_lock(&cdev->lock); - for (np=cdev->nccis; np; np = np->next) { - seq_printf(m, "%d 0x%x\n", - cdev->ap.applid, - np->ncci); - } + list_for_each_entry(np, &cdev->nccis, list) + seq_printf(m, "%d 0x%x\n", cdev->ap.applid, np->ncci); mutex_unlock(&cdev->lock); } mutex_unlock(&capidev_list_lock); -- cgit v1.2.2 From 81d17fe5e29d863027824928e1c336baa9abfee9 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:23 +0000 Subject: CAPI: Switch capiminor list to array Using a plain array of pointers simplifies the management of capiminors. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 75 ++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 40 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 6704b2b004aa..46f85ae85f5f 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -85,7 +85,6 @@ struct datahandle_queue { }; struct capiminor { - struct list_head list; struct capincci *nccip; unsigned int minor; struct dentry *capifs_dentry; @@ -151,8 +150,8 @@ static LIST_HEAD(capidev_list); #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE -static DEFINE_RWLOCK(capiminor_list_lock); -static LIST_HEAD(capiminor_list); +static DEFINE_RWLOCK(capiminors_lock); +static struct capiminor **capiminors; /* -------- datahandles --------------------------------------------- */ @@ -213,8 +212,8 @@ static void capiminor_del_all_ack(struct capiminor *mp) static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) { - struct capiminor *mp, *p; - unsigned int minor = 0; + struct capiminor *mp; + unsigned int minor; unsigned long flags; mp = kzalloc(sizeof(*mp), GFP_KERNEL); @@ -233,31 +232,23 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) skb_queue_head_init(&mp->inqueue); skb_queue_head_init(&mp->outqueue); - /* Allocate the least unused minor number. - */ - write_lock_irqsave(&capiminor_list_lock, flags); - if (list_empty(&capiminor_list)) - list_add(&mp->list, &capiminor_list); - else { - list_for_each_entry(p, &capiminor_list, list) { - if (p->minor > minor) - break; - minor++; - } - - if (minor < capi_ttyminors) { - mp->minor = minor; - list_add(&mp->list, p->list.prev); + /* Allocate the least unused minor number. */ + write_lock_irqsave(&capiminors_lock, flags); + for (minor = 0; minor < capi_ttyminors; minor++) + if (!capiminors[minor]) { + capiminors[minor] = mp; + break; } - } - write_unlock_irqrestore(&capiminor_list_lock, flags); + write_unlock_irqrestore(&capiminors_lock, flags); - if (!(minor < capi_ttyminors)) { + if (minor == capi_ttyminors) { printk(KERN_NOTICE "capi: out of minors\n"); - kfree(mp); + kfree(mp); return NULL; } + mp->minor = minor; + return mp; } @@ -265,9 +256,9 @@ static void capiminor_free(struct capiminor *mp) { unsigned long flags; - write_lock_irqsave(&capiminor_list_lock, flags); - list_del(&mp->list); - write_unlock_irqrestore(&capiminor_list_lock, flags); + write_lock_irqsave(&capiminors_lock, flags); + capiminors[mp->minor] = NULL; + write_unlock_irqrestore(&capiminors_lock, flags); kfree_skb(mp->ttyskb); mp->ttyskb = NULL; @@ -279,20 +270,16 @@ static void capiminor_free(struct capiminor *mp) static struct capiminor *capiminor_find(unsigned int minor) { - struct list_head *l; - struct capiminor *p = NULL; + struct capiminor *mp; - read_lock(&capiminor_list_lock); - list_for_each(l, &capiminor_list) { - p = list_entry(l, struct capiminor, list); - if (p->minor == minor) - break; - } - read_unlock(&capiminor_list_lock); - if (l == &capiminor_list) + if (minor >= capi_ttyminors) return NULL; - return p; + read_lock(&capiminors_lock); + mp = capiminors[minor]; + read_unlock(&capiminors_lock); + + return mp; } /* -------- struct capincci ----------------------------------------- */ @@ -1329,10 +1316,16 @@ static int capinc_tty_init(void) if (capi_ttyminors <= 0) capi_ttyminors = CAPINC_NR_PORTS; - drv = alloc_tty_driver(capi_ttyminors); - if (!drv) + capiminors = kzalloc(sizeof(struct capi_minor *) * capi_ttyminors, + GFP_KERNEL); + if (!capiminors) return -ENOMEM; + drv = alloc_tty_driver(capi_ttyminors); + if (!drv) { + kfree(capiminors); + return -ENOMEM; + } drv->owner = THIS_MODULE; drv->driver_name = "capi_nc"; drv->name = "capi"; @@ -1349,6 +1342,7 @@ static int capinc_tty_init(void) tty_set_operations(drv, &capinc_ops); if (tty_register_driver(drv)) { put_tty_driver(drv); + kfree(capiminors); printk(KERN_ERR "Couldn't register capi_nc driver\n"); return -1; } @@ -1363,6 +1357,7 @@ static void capinc_tty_exit(void) if ((retval = tty_unregister_driver(drv))) printk(KERN_ERR "capi: failed to unregister capi_nc driver (%d)\n", retval); put_tty_driver(drv); + kfree(capiminors); } #else /* !CONFIG_ISDN_CAPI_MIDDLEWARE */ -- cgit v1.2.2 From e76b1544074b5fc7983a21fb1f51a7faf03d3179 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:24 +0000 Subject: CAPI: Clean up capinc_tty_init/exit Return proper error code if tty_register_driver fails. In contrast, tty_unregister_driver cannot practically fail, so drop that error handling. Finally, mark capinc_tty_init/exit with __init/__exit. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 46f85ae85f5f..c22b34976c24 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -1307,10 +1307,11 @@ static const struct tty_operations capinc_ops = { .send_xchar = capinc_tty_send_xchar, }; -static int capinc_tty_init(void) +static int __init capinc_tty_init(void) { struct tty_driver *drv; - + int err; + if (capi_ttyminors > CAPINC_MAX_PORTS) capi_ttyminors = CAPINC_MAX_PORTS; if (capi_ttyminors <= 0) @@ -1340,23 +1341,22 @@ static int capinc_tty_init(void) drv->init_termios.c_lflag = 0; drv->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_RESET_TERMIOS; tty_set_operations(drv, &capinc_ops); - if (tty_register_driver(drv)) { + + err = tty_register_driver(drv); + if (err) { put_tty_driver(drv); kfree(capiminors); printk(KERN_ERR "Couldn't register capi_nc driver\n"); - return -1; + return err; } capinc_tty_driver = drv; return 0; } -static void capinc_tty_exit(void) +static void __exit capinc_tty_exit(void) { - struct tty_driver *drv = capinc_tty_driver; - int retval; - if ((retval = tty_unregister_driver(drv))) - printk(KERN_ERR "capi: failed to unregister capi_nc driver (%d)\n", retval); - put_tty_driver(drv); + tty_unregister_driver(capinc_tty_driver); + put_tty_driver(capinc_tty_driver); kfree(capiminors); } -- cgit v1.2.2 From 40fb2d0da77df5d39f1ba8878502725ebb806554 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:25 +0000 Subject: CAPI: Dynamically register minor devices Register capiminors dynamically with the TTY core so that udev can make them show up as the NCCIs appear or disappear. This removes the need to check if the capiminor requested in capinc_tty_open actually exists. And this completely obsoletes capifs which will be scheduled for removal in a later patch. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index c22b34976c24..901b79bc3b56 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -153,6 +153,8 @@ static LIST_HEAD(capidev_list); static DEFINE_RWLOCK(capiminors_lock); static struct capiminor **capiminors; +static struct tty_driver *capinc_tty_driver; + /* -------- datahandles --------------------------------------------- */ static int capiminor_add_ack(struct capiminor *mp, u16 datahandle) @@ -213,6 +215,7 @@ static void capiminor_del_all_ack(struct capiminor *mp) static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) { struct capiminor *mp; + struct device *dev; unsigned int minor; unsigned long flags; @@ -243,19 +246,33 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) if (minor == capi_ttyminors) { printk(KERN_NOTICE "capi: out of minors\n"); - kfree(mp); - return NULL; + goto err_out1; } mp->minor = minor; + dev = tty_register_device(capinc_tty_driver, minor, NULL); + if (IS_ERR(dev)) + goto err_out2; + return mp; + +err_out2: + write_lock_irqsave(&capiminors_lock, flags); + capiminors[minor] = NULL; + write_unlock_irqrestore(&capiminors_lock, flags); + +err_out1: + kfree(mp); + return NULL; } static void capiminor_free(struct capiminor *mp) { unsigned long flags; + tty_unregister_device(capinc_tty_driver, mp->minor); + write_lock_irqsave(&capiminors_lock, flags); capiminors[mp->minor] = NULL; write_unlock_irqrestore(&capiminors_lock, flags); @@ -268,13 +285,10 @@ static void capiminor_free(struct capiminor *mp) kfree(mp); } -static struct capiminor *capiminor_find(unsigned int minor) +static struct capiminor *capiminor_get(unsigned int minor) { struct capiminor *mp; - if (minor >= capi_ttyminors) - return NULL; - read_lock(&capiminors_lock); mp = capiminors[minor]; read_unlock(&capiminors_lock); @@ -981,8 +995,7 @@ static int capinc_tty_open(struct tty_struct * tty, struct file * file) struct capiminor *mp; unsigned long flags; - if ((mp = capiminor_find(iminor(file->f_path.dentry->d_inode))) == NULL) - return -ENXIO; + mp = capiminor_get(iminor(file->f_path.dentry->d_inode)); if (mp->nccip == NULL) return -ENXIO; @@ -1284,8 +1297,6 @@ static void capinc_tty_send_xchar(struct tty_struct *tty, char ch) #endif } -static struct tty_driver *capinc_tty_driver; - static const struct tty_operations capinc_ops = { .open = capinc_tty_open, .close = capinc_tty_close, @@ -1339,7 +1350,9 @@ static int __init capinc_tty_init(void) drv->init_termios.c_oflag = OPOST | ONLCR; drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; drv->init_termios.c_lflag = 0; - drv->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_RESET_TERMIOS; + drv->flags = + TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS | + TTY_DRIVER_DYNAMIC_DEV; tty_set_operations(drv, &capinc_ops); err = tty_register_driver(drv); -- cgit v1.2.2 From e95ac143868752ad30d93068a6fc0b39cf3a1bf4 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:26 +0000 Subject: CAPI: Use dynamic major for NCCI TTYs by default No need to allocate a fixed major for this TTY, both capifs and udev make this transparent to the user. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 901b79bc3b56..b1de0cbea69e 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -60,10 +60,8 @@ module_param_named(major, capi_major, uint, 0); #define CAPINC_NR_PORTS 32 #define CAPINC_MAX_PORTS 256 -static int capi_ttymajor = 191; static int capi_ttyminors = CAPINC_NR_PORTS; -module_param_named(ttymajor, capi_ttymajor, uint, 0); module_param_named(ttyminors, capi_ttyminors, uint, 0); #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ @@ -301,6 +299,7 @@ static struct capiminor *capiminor_get(unsigned int minor) static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np) { struct capiminor *mp; + dev_t device; if (!(cdev->userflags & CAPIFLAG_HIGHJACKING)) return; @@ -311,9 +310,8 @@ static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np) #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "set mp->nccip\n"); #endif - mp->capifs_dentry = - capifs_new_ncci(mp->minor, - MKDEV(capi_ttymajor, mp->minor)); + device = MKDEV(capinc_tty_driver->major, mp->minor); + mp->capifs_dentry = capifs_new_ncci(mp->minor, device); } } @@ -1341,7 +1339,7 @@ static int __init capinc_tty_init(void) drv->owner = THIS_MODULE; drv->driver_name = "capi_nc"; drv->name = "capi"; - drv->major = capi_ttymajor; + drv->major = 0; drv->minor_start = 0; drv->type = TTY_DRIVER_TYPE_SERIAL; drv->subtype = SERIAL_TYPE_NORMAL; -- cgit v1.2.2 From 0159d5491fef4acadd116a989b671e1cd350382f Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:27 +0000 Subject: CAPI: Use kref on capiminor Install a reference counter for capiminor objects. Acquire it when obtaining a capiminor from the array during capinc_tty_open, drop it when closing the tty again. Another reference is held for the hook-up with capincci. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index b1de0cbea69e..732cdb585b2d 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -83,6 +83,8 @@ struct datahandle_queue { }; struct capiminor { + struct kref kref; + struct capincci *nccip; unsigned int minor; struct dentry *capifs_dentry; @@ -223,6 +225,8 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) return NULL; } + kref_init(&mp->kref); + mp->ap = ap; mp->ncci = ncci; mp->msgid = 0; @@ -265,18 +269,11 @@ err_out1: return NULL; } -static void capiminor_free(struct capiminor *mp) +static void capiminor_destroy(struct kref *kref) { - unsigned long flags; - - tty_unregister_device(capinc_tty_driver, mp->minor); - - write_lock_irqsave(&capiminors_lock, flags); - capiminors[mp->minor] = NULL; - write_unlock_irqrestore(&capiminors_lock, flags); + struct capiminor *mp = container_of(kref, struct capiminor, kref); kfree_skb(mp->ttyskb); - mp->ttyskb = NULL; skb_queue_purge(&mp->inqueue); skb_queue_purge(&mp->outqueue); capiminor_del_all_ack(mp); @@ -289,11 +286,31 @@ static struct capiminor *capiminor_get(unsigned int minor) read_lock(&capiminors_lock); mp = capiminors[minor]; + if (mp) + kref_get(&mp->kref); read_unlock(&capiminors_lock); return mp; } +static inline void capiminor_put(struct capiminor *mp) +{ + kref_put(&mp->kref, capiminor_destroy); +} + +static void capiminor_free(struct capiminor *mp) +{ + unsigned long flags; + + tty_unregister_device(capinc_tty_driver, mp->minor); + + write_lock_irqsave(&capiminors_lock, flags); + capiminors[mp->minor] = NULL; + write_unlock_irqrestore(&capiminors_lock, flags); + + capiminor_put(mp); +} + /* -------- struct capincci ----------------------------------------- */ static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np) @@ -1029,6 +1046,8 @@ static void capinc_tty_close(struct tty_struct * tty, struct file * file) #endif if (mp->nccip == NULL) capiminor_free(mp); + + capiminor_put(mp); } #ifdef _DEBUG_REFCOUNT -- cgit v1.2.2 From 46324511809251adbedb874cc08692e247f7ed68 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:28 +0000 Subject: CAPI: Establish install/cleanup handlers for capiminor TTYs Properly associate/disassociate a capiminor object with its TTY via the install/cleanup handlers instead of trying to guess first open and last close. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 732cdb585b2d..3e4997ac67ae 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -1005,16 +1005,34 @@ static const struct file_operations capi_fops = #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE /* -------- tty_operations for capincci ----------------------------- */ -static int capinc_tty_open(struct tty_struct * tty, struct file * file) +static int +capinc_tty_install(struct tty_driver *driver, struct tty_struct *tty) { - struct capiminor *mp; - unsigned long flags; + int idx = tty->index; + struct capiminor *mp = capiminor_get(idx); + int ret = tty_init_termios(tty); + + if (ret == 0) { + tty_driver_kref_get(driver); + tty->count++; + tty->driver_data = mp; + driver->ttys[idx] = tty; + } else + capiminor_put(mp); + return ret; +} - mp = capiminor_get(iminor(file->f_path.dentry->d_inode)); - if (mp->nccip == NULL) - return -ENXIO; +static void capinc_tty_cleanup(struct tty_struct *tty) +{ + struct capiminor *mp = tty->driver_data; + tty->driver_data = NULL; + capiminor_put(mp); +} - tty->driver_data = (void *)mp; +static int capinc_tty_open(struct tty_struct * tty, struct file * file) +{ + struct capiminor *mp = tty->driver_data; + unsigned long flags; spin_lock_irqsave(&workaround_lock, flags); if (atomic_read(&mp->ttyopencount) == 0) @@ -1030,15 +1048,12 @@ static int capinc_tty_open(struct tty_struct * tty, struct file * file) static void capinc_tty_close(struct tty_struct * tty, struct file * file) { - struct capiminor *mp; + struct capiminor *mp = tty->driver_data; - mp = (struct capiminor *)tty->driver_data; - if (mp) { if (atomic_dec_and_test(&mp->ttyopencount)) { #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "capinc_tty_close lastclose\n"); #endif - tty->driver_data = NULL; mp->tty = NULL; } #ifdef _DEBUG_REFCOUNT @@ -1047,9 +1062,6 @@ static void capinc_tty_close(struct tty_struct * tty, struct file * file) if (mp->nccip == NULL) capiminor_free(mp); - capiminor_put(mp); - } - #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "capinc_tty_close\n"); #endif @@ -1333,6 +1345,8 @@ static const struct tty_operations capinc_ops = { .flush_buffer = capinc_tty_flush_buffer, .set_ldisc = capinc_tty_set_ldisc, .send_xchar = capinc_tty_send_xchar, + .install = capinc_tty_install, + .cleanup = capinc_tty_cleanup, }; static int __init capinc_tty_init(void) -- cgit v1.2.2 From fb4b4881ef951f6ed8fb8564ca1821dea10778c4 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:29 +0000 Subject: CAPI: Use tty_port to keep track of capiminor's tty Use the reference management features of tty_port to look up and drop again the tty_struct associated with a capiminor. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 94 +++++++++++++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 32 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 3e4997ac67ae..e164a8fb9693 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -94,7 +94,7 @@ struct capiminor { u16 datahandle; u16 msgid; - struct tty_struct *tty; + struct tty_port port; int ttyinstop; int ttyoutstop; struct sk_buff *ttyskb; @@ -212,6 +212,8 @@ static void capiminor_del_all_ack(struct capiminor *mp) /* -------- struct capiminor ---------------------------------------- */ +static const struct tty_port_operations capiminor_port_ops; /* we have none */ + static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) { struct capiminor *mp; @@ -237,6 +239,9 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) skb_queue_head_init(&mp->inqueue); skb_queue_head_init(&mp->outqueue); + tty_port_init(&mp->port); + mp->port.ops = &capiminor_port_ops; + /* Allocate the least unused minor number. */ write_lock_irqsave(&capiminors_lock, flags); for (minor = 0; minor < capi_ttyminors; minor++) @@ -335,18 +340,22 @@ static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np) static void capincci_free_minor(struct capincci *np) { struct capiminor *mp = np->minorp; + struct tty_struct *tty; if (mp) { capifs_free_ncci(mp->capifs_dentry); - if (mp->tty) { + + tty = tty_port_tty_get(&mp->port); + if (tty) { mp->nccip = NULL; #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "reset mp->nccip\n"); #endif - tty_hangup(mp->tty); - } else { - capiminor_free(mp); + tty_hangup(tty); + tty_kref_put(tty); } + + capiminor_free(mp); } } @@ -433,44 +442,48 @@ gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb) static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb) { + struct tty_struct *tty; struct sk_buff *nskb; int datalen; u16 errcode, datahandle; struct tty_ldisc *ld; - + int ret = -1; + datalen = skb->len - CAPIMSG_LEN(skb->data); - if (mp->tty == NULL) - { + + tty = tty_port_tty_get(&mp->port); + if (!tty) { #ifdef _DEBUG_DATAFLOW printk(KERN_DEBUG "capi: currently no receiver\n"); #endif return -1; } - ld = tty_ldisc_ref(mp->tty); - if (ld == NULL) - return -1; + ld = tty_ldisc_ref(tty); + if (!ld) + goto out1; + if (ld->ops->receive_buf == NULL) { #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) printk(KERN_DEBUG "capi: ldisc has no receive_buf function\n"); #endif - goto bad; + goto out2; } if (mp->ttyinstop) { #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) printk(KERN_DEBUG "capi: recv tty throttled\n"); #endif - goto bad; + goto out2; } - if (mp->tty->receive_room < datalen) { + if (tty->receive_room < datalen) { #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) printk(KERN_DEBUG "capi: no room in tty\n"); #endif - goto bad; + goto out2; } if ((nskb = gen_data_b3_resp_for(mp, skb)) == NULL) { printk(KERN_ERR "capi: gen_data_b3_resp failed\n"); - goto bad; + goto out2; } datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4); errcode = capi20_put_message(mp->ap, nskb); @@ -478,20 +491,21 @@ static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb) printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n", errcode); kfree_skb(nskb); - goto bad; + goto out2; } (void)skb_pull(skb, CAPIMSG_LEN(skb->data)); #ifdef _DEBUG_DATAFLOW printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n", datahandle, skb->len); #endif - ld->ops->receive_buf(mp->tty, skb->data, NULL, skb->len); + ld->ops->receive_buf(tty, skb->data, NULL, skb->len); kfree_skb(skb); + ret = 0; +out2: tty_ldisc_deref(ld); - return 0; -bad: - tty_ldisc_deref(ld); - return -1; +out1: + tty_kref_put(tty); + return ret; } static void handle_minor_recv(struct capiminor *mp) @@ -510,16 +524,22 @@ static void handle_minor_recv(struct capiminor *mp) static int handle_minor_send(struct capiminor *mp) { + struct tty_struct *tty; struct sk_buff *skb; u16 len; int count = 0; u16 errcode; u16 datahandle; - if (mp->tty && mp->ttyoutstop) { + tty = tty_port_tty_get(&mp->port); + if (!tty) + return 0; + + if (mp->ttyoutstop) { #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) printk(KERN_DEBUG "capi: send: tty stopped\n"); #endif + tty_kref_put(tty); return 0; } @@ -542,6 +562,7 @@ static int handle_minor_send(struct capiminor *mp) if (capiminor_add_ack(mp, datahandle) < 0) { skb_pull(skb, CAPI_DATA_B3_REQ_LEN); skb_queue_head(&mp->outqueue, skb); + tty_kref_put(tty); return count; } errcode = capi20_put_message(mp->ap, skb); @@ -568,6 +589,7 @@ static int handle_minor_send(struct capiminor *mp) mp->outbytes -= len; kfree_skb(skb); } + tty_kref_put(tty); return count; } @@ -578,6 +600,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) { struct capidev *cdev = ap->private; #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE + struct tty_struct *tty; struct capiminor *mp; u16 datahandle; #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ @@ -641,8 +664,11 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) #endif kfree_skb(skb); (void)capiminor_del_ack(mp, datahandle); - if (mp->tty) - tty_wakeup(mp->tty); + tty = tty_port_tty_get(&mp->port); + if (tty) { + tty_wakeup(tty); + tty_kref_put(tty); + } (void)handle_minor_send(mp); } else { @@ -1029,14 +1055,17 @@ static void capinc_tty_cleanup(struct tty_struct *tty) capiminor_put(mp); } -static int capinc_tty_open(struct tty_struct * tty, struct file * file) +static int capinc_tty_open(struct tty_struct *tty, struct file *filp) { struct capiminor *mp = tty->driver_data; unsigned long flags; + int err; + + err = tty_port_open(&mp->port, tty, filp); + if (err) + return err; spin_lock_irqsave(&workaround_lock, flags); - if (atomic_read(&mp->ttyopencount) == 0) - mp->tty = tty; atomic_inc(&mp->ttyopencount); #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "capinc_tty_open ocount=%d\n", atomic_read(&mp->ttyopencount)); @@ -1046,7 +1075,7 @@ static int capinc_tty_open(struct tty_struct * tty, struct file * file) return 0; } -static void capinc_tty_close(struct tty_struct * tty, struct file * file) +static void capinc_tty_close(struct tty_struct *tty, struct file *filp) { struct capiminor *mp = tty->driver_data; @@ -1054,17 +1083,15 @@ static void capinc_tty_close(struct tty_struct * tty, struct file * file) #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "capinc_tty_close lastclose\n"); #endif - mp->tty = NULL; } #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "capinc_tty_close ocount=%d\n", atomic_read(&mp->ttyopencount)); #endif - if (mp->nccip == NULL) - capiminor_free(mp); #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "capinc_tty_close\n"); #endif + tty_port_close(&mp->port, tty, filp); } static int capinc_tty_write(struct tty_struct * tty, @@ -1292,9 +1319,12 @@ static void capinc_tty_start(struct tty_struct *tty) static void capinc_tty_hangup(struct tty_struct *tty) { + struct capiminor *mp = tty->driver_data; + #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_hangup\n"); #endif + tty_port_hangup(&mp->port); } static int capinc_tty_break_ctl(struct tty_struct *tty, int state) -- cgit v1.2.2 From 2c8df72259d550ed6dc0b391feb5c2fc13892fb6 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:30 +0000 Subject: CAPI: Drop remaining NULL checks on tty->driver_data tty_struct's driver_data cannot be NULL, no need to test for it. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 64 +++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 33 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index e164a8fb9693..acc811bfe8e0 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -1097,7 +1097,7 @@ static void capinc_tty_close(struct tty_struct *tty, struct file *filp) static int capinc_tty_write(struct tty_struct * tty, const unsigned char *buf, int count) { - struct capiminor *mp = (struct capiminor *)tty->driver_data; + struct capiminor *mp = tty->driver_data; struct sk_buff *skb; unsigned long flags; @@ -1105,7 +1105,7 @@ static int capinc_tty_write(struct tty_struct * tty, printk(KERN_DEBUG "capinc_tty_write(count=%d)\n", count); #endif - if (!mp || !mp->nccip) { + if (!mp->nccip) { #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_write: mp or mp->ncci NULL\n"); #endif @@ -1140,7 +1140,7 @@ static int capinc_tty_write(struct tty_struct * tty, static int capinc_tty_put_char(struct tty_struct *tty, unsigned char ch) { - struct capiminor *mp = (struct capiminor *)tty->driver_data; + struct capiminor *mp = tty->driver_data; struct sk_buff *skb; unsigned long flags; int ret = 1; @@ -1149,7 +1149,7 @@ static int capinc_tty_put_char(struct tty_struct *tty, unsigned char ch) printk(KERN_DEBUG "capinc_put_char(%u)\n", ch); #endif - if (!mp || !mp->nccip) { + if (!mp->nccip) { #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_put_char: mp or mp->ncci NULL\n"); #endif @@ -1184,7 +1184,7 @@ static int capinc_tty_put_char(struct tty_struct *tty, unsigned char ch) static void capinc_tty_flush_chars(struct tty_struct *tty) { - struct capiminor *mp = (struct capiminor *)tty->driver_data; + struct capiminor *mp = tty->driver_data; struct sk_buff *skb; unsigned long flags; @@ -1192,7 +1192,7 @@ static void capinc_tty_flush_chars(struct tty_struct *tty) printk(KERN_DEBUG "capinc_tty_flush_chars\n"); #endif - if (!mp || !mp->nccip) { + if (!mp->nccip) { #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_flush_chars: mp or mp->ncci NULL\n"); #endif @@ -1213,9 +1213,10 @@ static void capinc_tty_flush_chars(struct tty_struct *tty) static int capinc_tty_write_room(struct tty_struct *tty) { - struct capiminor *mp = (struct capiminor *)tty->driver_data; + struct capiminor *mp = tty->driver_data; int room; - if (!mp || !mp->nccip) { + + if (!mp->nccip) { #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_write_room: mp or mp->ncci NULL\n"); #endif @@ -1231,8 +1232,9 @@ static int capinc_tty_write_room(struct tty_struct *tty) static int capinc_tty_chars_in_buffer(struct tty_struct *tty) { - struct capiminor *mp = (struct capiminor *)tty->driver_data; - if (!mp || !mp->nccip) { + struct capiminor *mp = tty->driver_data; + + if (!mp->nccip) { #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_chars_in_buffer: mp or mp->ncci NULL\n"); #endif @@ -1266,55 +1268,51 @@ static void capinc_tty_set_termios(struct tty_struct *tty, struct ktermios * old #endif } -static void capinc_tty_throttle(struct tty_struct * tty) +static void capinc_tty_throttle(struct tty_struct *tty) { - struct capiminor *mp = (struct capiminor *)tty->driver_data; + struct capiminor *mp = tty->driver_data; #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_throttle\n"); #endif - if (mp) - mp->ttyinstop = 1; + mp->ttyinstop = 1; } -static void capinc_tty_unthrottle(struct tty_struct * tty) +static void capinc_tty_unthrottle(struct tty_struct *tty) { - struct capiminor *mp = (struct capiminor *)tty->driver_data; + struct capiminor *mp = tty->driver_data; unsigned long flags; + #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_unthrottle\n"); #endif - if (mp) { - spin_lock_irqsave(&workaround_lock, flags); - mp->ttyinstop = 0; - handle_minor_recv(mp); - spin_unlock_irqrestore(&workaround_lock, flags); - } + spin_lock_irqsave(&workaround_lock, flags); + mp->ttyinstop = 0; + handle_minor_recv(mp); + spin_unlock_irqrestore(&workaround_lock, flags); } static void capinc_tty_stop(struct tty_struct *tty) { - struct capiminor *mp = (struct capiminor *)tty->driver_data; + struct capiminor *mp = tty->driver_data; + #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_stop\n"); #endif - if (mp) { - mp->ttyoutstop = 1; - } + mp->ttyoutstop = 1; } static void capinc_tty_start(struct tty_struct *tty) { - struct capiminor *mp = (struct capiminor *)tty->driver_data; + struct capiminor *mp = tty->driver_data; unsigned long flags; + #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_start\n"); #endif - if (mp) { - spin_lock_irqsave(&workaround_lock, flags); - mp->ttyoutstop = 0; - (void)handle_minor_send(mp); - spin_unlock_irqrestore(&workaround_lock, flags); - } + spin_lock_irqsave(&workaround_lock, flags); + mp->ttyoutstop = 0; + (void)handle_minor_send(mp); + spin_unlock_irqrestore(&workaround_lock, flags); } static void capinc_tty_hangup(struct tty_struct *tty) -- cgit v1.2.2 From 30bced91d93f7523bf23432d71d882d6b5d6cff6 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:31 +0000 Subject: CAPI: Issue synchronous hangup on capincci_free_minor capincci_free and, thus, capincci_free_minor runs in process context, so we can issue the hangup of the associated TTY synchronously. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index acc811bfe8e0..b382edeeee18 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -351,7 +351,7 @@ static void capincci_free_minor(struct capincci *np) #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "reset mp->nccip\n"); #endif - tty_hangup(tty); + tty_vhangup(tty); tty_kref_put(tty); } -- cgit v1.2.2 From 6576c2891adacad81ea0b24f0704ecac9fc727cb Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:32 +0000 Subject: CAPI: Drop obsolete nccip from capiminor struct The nccip in capiminor used to serve as an indicator that the NCCI was close. But we don't need this, we issue a hangup on capincci_free_minor. So drop this legacy. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 44 +------------------------------------------- 1 file changed, 1 insertion(+), 43 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index b382edeeee18..cf5e996ac448 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -85,7 +85,6 @@ struct datahandle_queue { struct capiminor { struct kref kref; - struct capincci *nccip; unsigned int minor; struct dentry *capifs_dentry; @@ -328,10 +327,6 @@ static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np) mp = np->minorp = capiminor_alloc(&cdev->ap, np->ncci); if (mp) { - mp->nccip = np; -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "set mp->nccip\n"); -#endif device = MKDEV(capinc_tty_driver->major, mp->minor); mp->capifs_dentry = capifs_new_ncci(mp->minor, device); } @@ -347,10 +342,6 @@ static void capincci_free_minor(struct capincci *np) tty = tty_port_tty_get(&mp->port); if (tty) { - mp->nccip = NULL; -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "reset mp->nccip\n"); -#endif tty_vhangup(tty); tty_kref_put(tty); } @@ -1094,7 +1085,7 @@ static void capinc_tty_close(struct tty_struct *tty, struct file *filp) tty_port_close(&mp->port, tty, filp); } -static int capinc_tty_write(struct tty_struct * tty, +static int capinc_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct capiminor *mp = tty->driver_data; @@ -1105,13 +1096,6 @@ static int capinc_tty_write(struct tty_struct * tty, printk(KERN_DEBUG "capinc_tty_write(count=%d)\n", count); #endif - if (!mp->nccip) { -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_write: mp or mp->ncci NULL\n"); -#endif - return 0; - } - spin_lock_irqsave(&workaround_lock, flags); skb = mp->ttyskb; if (skb) { @@ -1149,13 +1133,6 @@ static int capinc_tty_put_char(struct tty_struct *tty, unsigned char ch) printk(KERN_DEBUG "capinc_put_char(%u)\n", ch); #endif - if (!mp->nccip) { -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_put_char: mp or mp->ncci NULL\n"); -#endif - return 0; - } - spin_lock_irqsave(&workaround_lock, flags); skb = mp->ttyskb; if (skb) { @@ -1192,13 +1169,6 @@ static void capinc_tty_flush_chars(struct tty_struct *tty) printk(KERN_DEBUG "capinc_tty_flush_chars\n"); #endif - if (!mp->nccip) { -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_flush_chars: mp or mp->ncci NULL\n"); -#endif - return; - } - spin_lock_irqsave(&workaround_lock, flags); skb = mp->ttyskb; if (skb) { @@ -1216,12 +1186,6 @@ static int capinc_tty_write_room(struct tty_struct *tty) struct capiminor *mp = tty->driver_data; int room; - if (!mp->nccip) { -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_write_room: mp or mp->ncci NULL\n"); -#endif - return 0; - } room = CAPINC_MAX_SENDQUEUE-skb_queue_len(&mp->outqueue); room *= CAPI_MAX_BLKSIZE; #ifdef _DEBUG_TTYFUNCS @@ -1234,12 +1198,6 @@ static int capinc_tty_chars_in_buffer(struct tty_struct *tty) { struct capiminor *mp = tty->driver_data; - if (!mp->nccip) { -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_chars_in_buffer: mp or mp->ncci NULL\n"); -#endif - return 0; - } #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_chars_in_buffer = %d nack=%d sq=%d rq=%d\n", mp->outbytes, mp->nack, -- cgit v1.2.2 From 3d5d30fe7a6aa4c9d63dc4fe6b6da6abac423bc2 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:33 +0000 Subject: CAPI: Clean up capiminors_lock Use a plain spin lock for capiminors_lock, drop inconsistent irqsafe acquisitions (it's only used in process context anyway). Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index cf5e996ac448..0b264b4565c8 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -149,7 +149,7 @@ static LIST_HEAD(capidev_list); #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE -static DEFINE_RWLOCK(capiminors_lock); +static DEFINE_SPINLOCK(capiminors_lock); static struct capiminor **capiminors; static struct tty_driver *capinc_tty_driver; @@ -218,7 +218,6 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) struct capiminor *mp; struct device *dev; unsigned int minor; - unsigned long flags; mp = kzalloc(sizeof(*mp), GFP_KERNEL); if (!mp) { @@ -242,13 +241,13 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) mp->port.ops = &capiminor_port_ops; /* Allocate the least unused minor number. */ - write_lock_irqsave(&capiminors_lock, flags); + spin_lock(&capiminors_lock); for (minor = 0; minor < capi_ttyminors; minor++) if (!capiminors[minor]) { capiminors[minor] = mp; break; } - write_unlock_irqrestore(&capiminors_lock, flags); + spin_unlock(&capiminors_lock); if (minor == capi_ttyminors) { printk(KERN_NOTICE "capi: out of minors\n"); @@ -264,9 +263,9 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) return mp; err_out2: - write_lock_irqsave(&capiminors_lock, flags); + spin_lock(&capiminors_lock); capiminors[minor] = NULL; - write_unlock_irqrestore(&capiminors_lock, flags); + spin_unlock(&capiminors_lock); err_out1: kfree(mp); @@ -288,11 +287,11 @@ static struct capiminor *capiminor_get(unsigned int minor) { struct capiminor *mp; - read_lock(&capiminors_lock); + spin_lock(&capiminors_lock); mp = capiminors[minor]; if (mp) kref_get(&mp->kref); - read_unlock(&capiminors_lock); + spin_unlock(&capiminors_lock); return mp; } @@ -304,13 +303,11 @@ static inline void capiminor_put(struct capiminor *mp) static void capiminor_free(struct capiminor *mp) { - unsigned long flags; - tty_unregister_device(capinc_tty_driver, mp->minor); - write_lock_irqsave(&capiminors_lock, flags); + spin_lock(&capiminors_lock); capiminors[mp->minor] = NULL; - write_unlock_irqrestore(&capiminors_lock, flags); + spin_unlock(&capiminors_lock); capiminor_put(mp); } -- cgit v1.2.2 From a84fdf41b25ad4c2b83e7c8ca87268fdbe6207d1 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:34 +0000 Subject: CAPI: Drop atomic ttyopencount Not needed, tty->count keeps track of this information. At this chance, drop traces of ancient attempts to debug this logic via _DEBUG_REFCOUNT. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 0b264b4565c8..867589a5916a 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -45,7 +45,6 @@ MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface"); MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); -#undef _DEBUG_REFCOUNT /* alloc/free and open/close debug */ #undef _DEBUG_TTYFUNCS /* call to tty_driver */ #undef _DEBUG_DATAFLOW /* data flow */ @@ -97,7 +96,6 @@ struct capiminor { int ttyinstop; int ttyoutstop; struct sk_buff *ttyskb; - atomic_t ttyopencount; struct sk_buff_head inqueue; int inbytes; @@ -230,7 +228,6 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) mp->ap = ap; mp->ncci = ncci; mp->msgid = 0; - atomic_set(&mp->ttyopencount,0); INIT_LIST_HEAD(&mp->ackqueue); spin_lock_init(&mp->ackqlock); @@ -350,8 +347,17 @@ static void capincci_free_minor(struct capincci *np) static inline unsigned int capincci_minor_opencount(struct capincci *np) { struct capiminor *mp = np->minorp; + unsigned int count = 0; + struct tty_struct *tty; - return mp ? atomic_read(&mp->ttyopencount) : 0; + if (mp) { + tty = tty_port_tty_get(&mp->port); + if (tty) { + count = tty->count; + tty_kref_put(tty); + } + } + return count; } #else /* !CONFIG_ISDN_CAPI_MIDDLEWARE */ @@ -1054,10 +1060,6 @@ static int capinc_tty_open(struct tty_struct *tty, struct file *filp) return err; spin_lock_irqsave(&workaround_lock, flags); - atomic_inc(&mp->ttyopencount); -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "capinc_tty_open ocount=%d\n", atomic_read(&mp->ttyopencount)); -#endif handle_minor_recv(mp); spin_unlock_irqrestore(&workaround_lock, flags); return 0; @@ -1067,18 +1069,6 @@ static void capinc_tty_close(struct tty_struct *tty, struct file *filp) { struct capiminor *mp = tty->driver_data; - if (atomic_dec_and_test(&mp->ttyopencount)) { -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "capinc_tty_close lastclose\n"); -#endif - } -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "capinc_tty_close ocount=%d\n", atomic_read(&mp->ttyopencount)); -#endif - -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "capinc_tty_close\n"); -#endif tty_port_close(&mp->port, tty, filp); } -- cgit v1.2.2 From b75b2eedcbf6458c68713c772c2ade83ab7a55f0 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:35 +0000 Subject: CAPI: Drop handle_minor_recv from capinc_tty_write Sending a message down the CAPI stack may trigger the reception of an answer, but this will go through capi_recv_message and call handle_minor_recv from there. There is no need to walk the receive queue on capinc_tty_write. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 867589a5916a..554fa1b36d13 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -1104,7 +1104,6 @@ static int capinc_tty_write(struct tty_struct *tty, skb_queue_tail(&mp->outqueue, skb); mp->outbytes += skb->len; (void)handle_minor_send(mp); - (void)handle_minor_recv(mp); spin_unlock_irqrestore(&workaround_lock, flags); return count; } -- cgit v1.2.2 From a11ef7be8e982426e9fbbfc84fa0c01d23ce05c3 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:36 +0000 Subject: CAPI: Rework capiminor RX handler Avoid re-queuing skbs unless the error detected in handle_recv_skb is expected to be recoverable such as lacking memory, a full CAPI queue, a full TTY input buffer, or a not yet existing TTY. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 60 ++++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 22 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 554fa1b36d13..c5c54fab50eb 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -436,15 +436,13 @@ gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb) static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb) { + unsigned int datalen = skb->len - CAPIMSG_LEN(skb->data); struct tty_struct *tty; struct sk_buff *nskb; - int datalen; u16 errcode, datahandle; struct tty_ldisc *ld; int ret = -1; - datalen = skb->len - CAPIMSG_LEN(skb->data); - tty = tty_port_tty_get(&mp->port); if (!tty) { #ifdef _DEBUG_DATAFLOW @@ -454,50 +452,68 @@ static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb) } ld = tty_ldisc_ref(tty); - if (!ld) - goto out1; + if (!ld) { + /* fatal error, do not requeue */ + ret = 0; + kfree_skb(skb); + goto deref_tty; + } if (ld->ops->receive_buf == NULL) { #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) printk(KERN_DEBUG "capi: ldisc has no receive_buf function\n"); #endif - goto out2; + /* fatal error, do not requeue */ + goto free_skb; } if (mp->ttyinstop) { #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) printk(KERN_DEBUG "capi: recv tty throttled\n"); #endif - goto out2; + goto deref_ldisc; } + if (tty->receive_room < datalen) { #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) printk(KERN_DEBUG "capi: no room in tty\n"); #endif - goto out2; + goto deref_ldisc; } - if ((nskb = gen_data_b3_resp_for(mp, skb)) == NULL) { + + nskb = gen_data_b3_resp_for(mp, skb); + if (!nskb) { printk(KERN_ERR "capi: gen_data_b3_resp failed\n"); - goto out2; + goto deref_ldisc; } - datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4); + + datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN + 4); + errcode = capi20_put_message(mp->ap, nskb); - if (errcode != CAPI_NOERROR) { + + if (errcode == CAPI_NOERROR) { + skb_pull(skb, CAPIMSG_LEN(skb->data)); +#ifdef _DEBUG_DATAFLOW + printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n", + datahandle, skb->len); +#endif + ld->ops->receive_buf(tty, skb->data, NULL, skb->len); + } else { printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n", errcode); kfree_skb(nskb); - goto out2; + + if (errcode == CAPI_SENDQUEUEFULL) + goto deref_ldisc; } - (void)skb_pull(skb, CAPIMSG_LEN(skb->data)); -#ifdef _DEBUG_DATAFLOW - printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n", - datahandle, skb->len); -#endif - ld->ops->receive_buf(tty, skb->data, NULL, skb->len); - kfree_skb(skb); + +free_skb: ret = 0; -out2: + kfree_skb(skb); + +deref_ldisc: tty_ldisc_deref(ld); -out1: + +deref_tty: tty_kref_put(tty); return ret; } -- cgit v1.2.2 From 42651b5c1aabf5eb60fbe98375ba127f4f6eb943 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:37 +0000 Subject: CAPI: Rename datahandle_queue -> ackqueue_entry This struct is describing a queue entry, not the queue itself. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index c5c54fab50eb..9d4750a0aece 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -76,7 +76,7 @@ struct capidev; struct capincci; struct capiminor; -struct datahandle_queue { +struct ackqueue_entry { struct list_head list; u16 datahandle; }; @@ -156,7 +156,7 @@ static struct tty_driver *capinc_tty_driver; static int capiminor_add_ack(struct capiminor *mp, u16 datahandle) { - struct datahandle_queue *n; + struct ackqueue_entry *n; unsigned long flags; n = kmalloc(sizeof(*n), GFP_ATOMIC); @@ -175,7 +175,7 @@ static int capiminor_add_ack(struct capiminor *mp, u16 datahandle) static int capiminor_del_ack(struct capiminor *mp, u16 datahandle) { - struct datahandle_queue *p, *tmp; + struct ackqueue_entry *p, *tmp; unsigned long flags; spin_lock_irqsave(&mp->ackqlock, flags); @@ -194,7 +194,7 @@ static int capiminor_del_ack(struct capiminor *mp, u16 datahandle) static void capiminor_del_all_ack(struct capiminor *mp) { - struct datahandle_queue *p, *tmp; + struct ackqueue_entry *p, *tmp; unsigned long flags; spin_lock_irqsave(&mp->ackqlock, flags); -- cgit v1.2.2 From 42792713f7f2664cf07501e1244d6da33a73ffc1 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:38 +0000 Subject: CAPI: Use atomics for capiminor's datahandle and msgid The capiminor members datahandle and msgid are incremented outside any lock, so better do this atomically. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 9d4750a0aece..08d5a8aa2fec 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -87,10 +87,10 @@ struct capiminor { unsigned int minor; struct dentry *capifs_dentry; - struct capi20_appl *ap; - u32 ncci; - u16 datahandle; - u16 msgid; + struct capi20_appl *ap; + u32 ncci; + atomic_t datahandle; + atomic_t msgid; struct tty_port port; int ttyinstop; @@ -227,7 +227,6 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) mp->ap = ap; mp->ncci = ncci; - mp->msgid = 0; INIT_LIST_HEAD(&mp->ackqueue); spin_lock_init(&mp->ackqlock); @@ -427,7 +426,7 @@ gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb) capimsg_setu16(s, 2, mp->ap->applid); capimsg_setu8 (s, 4, CAPI_DATA_B3); capimsg_setu8 (s, 5, CAPI_RESP); - capimsg_setu16(s, 6, mp->msgid++); + capimsg_setu16(s, 6, atomic_inc_return(&mp->msgid)); capimsg_setu32(s, 8, mp->ncci); capimsg_setu16(s, 12, datahandle); } @@ -554,7 +553,7 @@ static int handle_minor_send(struct capiminor *mp) } while ((skb = skb_dequeue(&mp->outqueue)) != NULL) { - datahandle = mp->datahandle; + datahandle = atomic_inc_return(&mp->datahandle); len = (u16)skb->len; skb_push(skb, CAPI_DATA_B3_REQ_LEN); memset(skb->data, 0, CAPI_DATA_B3_REQ_LEN); @@ -562,7 +561,7 @@ static int handle_minor_send(struct capiminor *mp) capimsg_setu16(skb->data, 2, mp->ap->applid); capimsg_setu8 (skb->data, 4, CAPI_DATA_B3); capimsg_setu8 (skb->data, 5, CAPI_REQ); - capimsg_setu16(skb->data, 6, mp->msgid++); + capimsg_setu16(skb->data, 6, atomic_inc_return(&mp->msgid)); capimsg_setu32(skb->data, 8, mp->ncci); /* NCCI */ capimsg_setu32(skb->data, 12, (u32)(long)skb->data);/* Data32 */ capimsg_setu16(skb->data, 16, len); /* Data length */ @@ -577,7 +576,6 @@ static int handle_minor_send(struct capiminor *mp) } errcode = capi20_put_message(mp->ap, skb); if (errcode == CAPI_NOERROR) { - mp->datahandle++; count++; mp->outbytes -= len; #ifdef _DEBUG_DATAFLOW -- cgit v1.2.2 From 68d7347b280b4c1f8253c0676a520fb754f213c7 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:39 +0000 Subject: CAPI: Drop capiminor's unused inbytes counter The inbytes counter was only updated but never read. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 08d5a8aa2fec..be85c8c1e8b4 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -98,7 +98,6 @@ struct capiminor { struct sk_buff *ttyskb; struct sk_buff_head inqueue; - int inbytes; struct sk_buff_head outqueue; int outbytes; @@ -520,15 +519,12 @@ deref_tty: static void handle_minor_recv(struct capiminor *mp) { struct sk_buff *skb; - while ((skb = skb_dequeue(&mp->inqueue)) != NULL) { - unsigned int len = skb->len; - mp->inbytes -= len; + + while ((skb = skb_dequeue(&mp->inqueue)) != NULL) if (handle_recv_skb(mp, skb) < 0) { skb_queue_head(&mp->inqueue, skb); - mp->inbytes += len; return; } - } } static int handle_minor_send(struct capiminor *mp) @@ -659,7 +655,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) datahandle, skb->len-CAPIMSG_LEN(skb->data)); #endif skb_queue_tail(&mp->inqueue, skb); - mp->inbytes += skb->len; + handle_minor_recv(mp); } else if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF) { -- cgit v1.2.2 From dfbb84ffe94e75e2d56250fa948db40f6c62093f Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:40 +0000 Subject: CAPI: Fix locking around capiminor's output queue and drop workaround_lock Introduce outlock as a spin lock that protects capiminor's outqueue, outbytes and outskb (formerly known as ttyskb). outlock can be acquired from soft-IRQ context via capinc_write, so make it bh-safe. This finally removes the last reason for keeping the workaround lock around (which was incomplete and partly broken anyway). And as we no longer call handle_recv_skb in atomic context, gen_data_b3_resp_for can use non-atomic allocation now. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 126 +++++++++++++++++++++++++---------------------- 1 file changed, 67 insertions(+), 59 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index be85c8c1e8b4..074496fae8da 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -95,11 +95,13 @@ struct capiminor { struct tty_port port; int ttyinstop; int ttyoutstop; - struct sk_buff *ttyskb; - struct sk_buff_head inqueue; - struct sk_buff_head outqueue; - int outbytes; + struct sk_buff_head inqueue; + + struct sk_buff_head outqueue; + int outbytes; + struct sk_buff *outskb; + spinlock_t outlock; /* transmit path */ struct list_head ackqueue; @@ -107,15 +109,6 @@ struct capiminor { spinlock_t ackqlock; }; -/* FIXME: The following lock is a sledgehammer-workaround to a - * locking issue with the capiminor (and maybe other) data structure(s). - * Access to this data is done in a racy way and crashes the machine with - * a FritzCard DSL driver; sooner or later. This is a workaround - * which trades scalability vs stability, so it doesn't crash the kernel anymore. - * The correct (and scalable) fix for the issue seems to require - * an API change to the drivers... . */ -static DEFINE_SPINLOCK(workaround_lock); - struct capincci { struct list_head list; u32 ncci; @@ -231,6 +224,7 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) skb_queue_head_init(&mp->inqueue); skb_queue_head_init(&mp->outqueue); + spin_lock_init(&mp->outlock); tty_port_init(&mp->port); mp->port.ops = &capiminor_port_ops; @@ -271,7 +265,7 @@ static void capiminor_destroy(struct kref *kref) { struct capiminor *mp = container_of(kref, struct capiminor, kref); - kfree_skb(mp->ttyskb); + kfree_skb(mp->outskb); skb_queue_purge(&mp->inqueue); skb_queue_purge(&mp->outqueue); capiminor_del_all_ack(mp); @@ -417,7 +411,7 @@ static struct sk_buff * gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb) { struct sk_buff *nskb; - nskb = alloc_skb(CAPI_DATA_B3_RESP_LEN, GFP_ATOMIC); + nskb = alloc_skb(CAPI_DATA_B3_RESP_LEN, GFP_KERNEL); if (nskb) { u16 datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4+4+2); unsigned char *s = skb_put(nskb, CAPI_DATA_B3_RESP_LEN); @@ -548,9 +542,18 @@ static int handle_minor_send(struct capiminor *mp) return 0; } - while ((skb = skb_dequeue(&mp->outqueue)) != NULL) { - datahandle = atomic_inc_return(&mp->datahandle); + while (1) { + spin_lock_bh(&mp->outlock); + skb = __skb_dequeue(&mp->outqueue); + if (!skb) { + spin_unlock_bh(&mp->outlock); + break; + } len = (u16)skb->len; + mp->outbytes -= len; + spin_unlock_bh(&mp->outlock); + + datahandle = atomic_inc_return(&mp->datahandle); skb_push(skb, CAPI_DATA_B3_REQ_LEN); memset(skb->data, 0, CAPI_DATA_B3_REQ_LEN); capimsg_setu16(skb->data, 0, CAPI_DATA_B3_REQ_LEN); @@ -566,14 +569,18 @@ static int handle_minor_send(struct capiminor *mp) if (capiminor_add_ack(mp, datahandle) < 0) { skb_pull(skb, CAPI_DATA_B3_REQ_LEN); - skb_queue_head(&mp->outqueue, skb); + + spin_lock_bh(&mp->outlock); + __skb_queue_head(&mp->outqueue, skb); + mp->outbytes += len; + spin_unlock_bh(&mp->outlock); + tty_kref_put(tty); return count; } errcode = capi20_put_message(mp->ap, skb); if (errcode == CAPI_NOERROR) { count++; - mp->outbytes -= len; #ifdef _DEBUG_DATAFLOW printk(KERN_DEBUG "capi: DATA_B3_REQ %u len=%u\n", datahandle, len); @@ -584,13 +591,17 @@ static int handle_minor_send(struct capiminor *mp) if (errcode == CAPI_SENDQUEUEFULL) { skb_pull(skb, CAPI_DATA_B3_REQ_LEN); - skb_queue_head(&mp->outqueue, skb); + + spin_lock_bh(&mp->outlock); + __skb_queue_head(&mp->outqueue, skb); + mp->outbytes += len; + spin_unlock_bh(&mp->outlock); + break; } /* ups, drop packet */ printk(KERN_ERR "capi: put_message = %x\n", errcode); - mp->outbytes -= len; kfree_skb(skb); } tty_kref_put(tty); @@ -609,7 +620,6 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) u16 datahandle; #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ struct capincci *np; - unsigned long flags; mutex_lock(&cdev->lock); @@ -621,7 +631,6 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_IND) capincci_alloc(cdev, CAPIMSG_NCCI(skb->data)); - spin_lock_irqsave(&workaround_lock, flags); if (CAPIMSG_COMMAND(skb->data) != CAPI_DATA_B3) { skb_queue_tail(&cdev->recvqueue, skb); wake_up_interruptible(&cdev->recvwait); @@ -683,7 +692,6 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ unlock_out: - spin_unlock_irqrestore(&workaround_lock, flags); mutex_unlock(&cdev->lock); } @@ -1062,16 +1070,13 @@ static void capinc_tty_cleanup(struct tty_struct *tty) static int capinc_tty_open(struct tty_struct *tty, struct file *filp) { struct capiminor *mp = tty->driver_data; - unsigned long flags; int err; err = tty_port_open(&mp->port, tty, filp); if (err) return err; - spin_lock_irqsave(&workaround_lock, flags); handle_minor_recv(mp); - spin_unlock_irqrestore(&workaround_lock, flags); return 0; } @@ -1087,71 +1092,78 @@ static int capinc_tty_write(struct tty_struct *tty, { struct capiminor *mp = tty->driver_data; struct sk_buff *skb; - unsigned long flags; #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_write(count=%d)\n", count); #endif - spin_lock_irqsave(&workaround_lock, flags); - skb = mp->ttyskb; + spin_lock_bh(&mp->outlock); + skb = mp->outskb; if (skb) { - mp->ttyskb = NULL; - skb_queue_tail(&mp->outqueue, skb); + mp->outskb = NULL; + __skb_queue_tail(&mp->outqueue, skb); mp->outbytes += skb->len; } skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+count, GFP_ATOMIC); if (!skb) { printk(KERN_ERR "capinc_tty_write: alloc_skb failed\n"); - spin_unlock_irqrestore(&workaround_lock, flags); + spin_unlock_bh(&mp->outlock); return -ENOMEM; } skb_reserve(skb, CAPI_DATA_B3_REQ_LEN); memcpy(skb_put(skb, count), buf, count); - skb_queue_tail(&mp->outqueue, skb); + __skb_queue_tail(&mp->outqueue, skb); mp->outbytes += skb->len; + spin_unlock_bh(&mp->outlock); + (void)handle_minor_send(mp); - spin_unlock_irqrestore(&workaround_lock, flags); + return count; } static int capinc_tty_put_char(struct tty_struct *tty, unsigned char ch) { struct capiminor *mp = tty->driver_data; + bool invoke_send = false; struct sk_buff *skb; - unsigned long flags; int ret = 1; #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_put_char(%u)\n", ch); #endif - spin_lock_irqsave(&workaround_lock, flags); - skb = mp->ttyskb; + spin_lock_bh(&mp->outlock); + skb = mp->outskb; if (skb) { if (skb_tailroom(skb) > 0) { *(skb_put(skb, 1)) = ch; - spin_unlock_irqrestore(&workaround_lock, flags); - return 1; + goto unlock_out; } - mp->ttyskb = NULL; - skb_queue_tail(&mp->outqueue, skb); + mp->outskb = NULL; + __skb_queue_tail(&mp->outqueue, skb); mp->outbytes += skb->len; - (void)handle_minor_send(mp); + invoke_send = true; } + skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+CAPI_MAX_BLKSIZE, GFP_ATOMIC); if (skb) { skb_reserve(skb, CAPI_DATA_B3_REQ_LEN); *(skb_put(skb, 1)) = ch; - mp->ttyskb = skb; + mp->outskb = skb; } else { printk(KERN_ERR "capinc_put_char: char %u lost\n", ch); ret = 0; } - spin_unlock_irqrestore(&workaround_lock, flags); + +unlock_out: + spin_unlock_bh(&mp->outlock); + + if (invoke_send) + (void)handle_minor_send(mp); + return ret; } @@ -1159,22 +1171,24 @@ static void capinc_tty_flush_chars(struct tty_struct *tty) { struct capiminor *mp = tty->driver_data; struct sk_buff *skb; - unsigned long flags; #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_flush_chars\n"); #endif - spin_lock_irqsave(&workaround_lock, flags); - skb = mp->ttyskb; + spin_lock_bh(&mp->outlock); + skb = mp->outskb; if (skb) { - mp->ttyskb = NULL; - skb_queue_tail(&mp->outqueue, skb); + mp->outskb = NULL; + __skb_queue_tail(&mp->outqueue, skb); mp->outbytes += skb->len; + spin_unlock_bh(&mp->outlock); + (void)handle_minor_send(mp); - } - (void)handle_minor_recv(mp); - spin_unlock_irqrestore(&workaround_lock, flags); + } else + spin_unlock_bh(&mp->outlock); + + handle_minor_recv(mp); } static int capinc_tty_write_room(struct tty_struct *tty) @@ -1234,15 +1248,12 @@ static void capinc_tty_throttle(struct tty_struct *tty) static void capinc_tty_unthrottle(struct tty_struct *tty) { struct capiminor *mp = tty->driver_data; - unsigned long flags; #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_unthrottle\n"); #endif - spin_lock_irqsave(&workaround_lock, flags); mp->ttyinstop = 0; handle_minor_recv(mp); - spin_unlock_irqrestore(&workaround_lock, flags); } static void capinc_tty_stop(struct tty_struct *tty) @@ -1258,15 +1269,12 @@ static void capinc_tty_stop(struct tty_struct *tty) static void capinc_tty_start(struct tty_struct *tty) { struct capiminor *mp = tty->driver_data; - unsigned long flags; #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_start\n"); #endif - spin_lock_irqsave(&workaround_lock, flags); mp->ttyoutstop = 0; (void)handle_minor_send(mp); - spin_unlock_irqrestore(&workaround_lock, flags); } static void capinc_tty_hangup(struct tty_struct *tty) -- cgit v1.2.2 From 2b72b5bd65f00bce786ca080aca27e91e90af6df Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:41 +0000 Subject: CAPI: Clean up capiminor_*_ack No need for irqsave acquisition of acklock, bh-safe is sufficient. Moverover, move kfree out of the lock and do not take acklock at all in capiminor_del_all_ack as we are the last user of the list here. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 074496fae8da..40b81b460e81 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -149,7 +149,6 @@ static struct tty_driver *capinc_tty_driver; static int capiminor_add_ack(struct capiminor *mp, u16 datahandle) { struct ackqueue_entry *n; - unsigned long flags; n = kmalloc(sizeof(*n), GFP_ATOMIC); if (unlikely(!n)) { @@ -158,44 +157,40 @@ static int capiminor_add_ack(struct capiminor *mp, u16 datahandle) } n->datahandle = datahandle; INIT_LIST_HEAD(&n->list); - spin_lock_irqsave(&mp->ackqlock, flags); + spin_lock_bh(&mp->ackqlock); list_add_tail(&n->list, &mp->ackqueue); mp->nack++; - spin_unlock_irqrestore(&mp->ackqlock, flags); + spin_unlock_bh(&mp->ackqlock); return 0; } static int capiminor_del_ack(struct capiminor *mp, u16 datahandle) { struct ackqueue_entry *p, *tmp; - unsigned long flags; - spin_lock_irqsave(&mp->ackqlock, flags); + spin_lock_bh(&mp->ackqlock); list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) { if (p->datahandle == datahandle) { list_del(&p->list); - kfree(p); mp->nack--; - spin_unlock_irqrestore(&mp->ackqlock, flags); + spin_unlock_bh(&mp->ackqlock); + kfree(p); return 0; } } - spin_unlock_irqrestore(&mp->ackqlock, flags); + spin_unlock_bh(&mp->ackqlock); return -1; } static void capiminor_del_all_ack(struct capiminor *mp) { struct ackqueue_entry *p, *tmp; - unsigned long flags; - spin_lock_irqsave(&mp->ackqlock, flags); list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) { list_del(&p->list); kfree(p); mp->nack--; } - spin_unlock_irqrestore(&mp->ackqlock, flags); } @@ -676,7 +671,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+2)); #endif kfree_skb(skb); - (void)capiminor_del_ack(mp, datahandle); + capiminor_del_ack(mp, datahandle); tty = tty_port_tty_get(&mp->port); if (tty) { tty_wakeup(tty); -- cgit v1.2.2 From eef0ced02840cdbc9045b24e73378401aae04d4c Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:42 +0000 Subject: CAPI: Drop return value of handle_minor_send We did not evaluate handle_minor_send's return value, just (void)'ed it away. Time for a cleanup. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 40b81b460e81..ee5837522f5a 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -516,25 +516,24 @@ static void handle_minor_recv(struct capiminor *mp) } } -static int handle_minor_send(struct capiminor *mp) +static void handle_minor_send(struct capiminor *mp) { struct tty_struct *tty; struct sk_buff *skb; u16 len; - int count = 0; u16 errcode; u16 datahandle; tty = tty_port_tty_get(&mp->port); if (!tty) - return 0; + return; if (mp->ttyoutstop) { #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) printk(KERN_DEBUG "capi: send: tty stopped\n"); #endif tty_kref_put(tty); - return 0; + return; } while (1) { @@ -570,12 +569,10 @@ static int handle_minor_send(struct capiminor *mp) mp->outbytes += len; spin_unlock_bh(&mp->outlock); - tty_kref_put(tty); - return count; + break; } errcode = capi20_put_message(mp->ap, skb); if (errcode == CAPI_NOERROR) { - count++; #ifdef _DEBUG_DATAFLOW printk(KERN_DEBUG "capi: DATA_B3_REQ %u len=%u\n", datahandle, len); @@ -600,7 +597,6 @@ static int handle_minor_send(struct capiminor *mp) kfree_skb(skb); } tty_kref_put(tty); - return count; } #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ @@ -677,7 +673,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) tty_wakeup(tty); tty_kref_put(tty); } - (void)handle_minor_send(mp); + handle_minor_send(mp); } else { /* ups, let capi application handle it :-) */ @@ -1114,7 +1110,7 @@ static int capinc_tty_write(struct tty_struct *tty, mp->outbytes += skb->len; spin_unlock_bh(&mp->outlock); - (void)handle_minor_send(mp); + handle_minor_send(mp); return count; } @@ -1157,7 +1153,7 @@ unlock_out: spin_unlock_bh(&mp->outlock); if (invoke_send) - (void)handle_minor_send(mp); + handle_minor_send(mp); return ret; } @@ -1179,7 +1175,7 @@ static void capinc_tty_flush_chars(struct tty_struct *tty) mp->outbytes += skb->len; spin_unlock_bh(&mp->outlock); - (void)handle_minor_send(mp); + handle_minor_send(mp); } else spin_unlock_bh(&mp->outlock); @@ -1269,7 +1265,7 @@ static void capinc_tty_start(struct tty_struct *tty) printk(KERN_DEBUG "capinc_tty_start\n"); #endif mp->ttyoutstop = 0; - (void)handle_minor_send(mp); + handle_minor_send(mp); } static void capinc_tty_hangup(struct tty_struct *tty) -- cgit v1.2.2 From c6af0437941c92179eeb51579f19423eacc5516c Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:43 +0000 Subject: CAPI: Drop special controller lookup from capi20_put_message This strange special rule to fall back to controller 1 cannot be derived from the CAPI specs and looks a lot like it was once dedicated to some out-of-tree driver, probably AVM's broken fcdsl2 (FRITZ!Card DSL v2.0). I found no in-tree user that needs this check, and I'm now taking care of the fcdsl2. So drop these bits from our stack. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/kcapi.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index 0b4c8a7396bc..ce9b05b9e93a 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -777,11 +777,8 @@ u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) * synchronizes this service with capi20_release. */ ctr = get_capi_ctr_by_nr(CAPIMSG_CONTROLLER(skb->data)); - if (!ctr || ctr->state != CAPI_CTR_RUNNING) { - ctr = get_capi_ctr_by_nr(1); /* XXX why? */ - if (!ctr || ctr->state != CAPI_CTR_RUNNING) - return CAPI_REGNOTINSTALLED; - } + if (!ctr || ctr->state != CAPI_CTR_RUNNING) + return CAPI_REGNOTINSTALLED; if (ctr->blocked) return CAPI_SENDQUEUEFULL; -- cgit v1.2.2 From 79e95f4717767e9ddc4dbec5d778f0c9970eed34 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:44 +0000 Subject: CAPI: Schedule capifs for removal With dynamic TTY nodes and the help of udev, we no longer need this special filesystem. Schedule it for removal in one year from now. As a last duty to this feature, move its help to right option so that users can read the rationale. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/Kconfig | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/Kconfig b/drivers/isdn/capi/Kconfig index b2a04755c96a..d607d465786e 100644 --- a/drivers/isdn/capi/Kconfig +++ b/drivers/isdn/capi/Kconfig @@ -35,18 +35,19 @@ config ISDN_CAPI_CAPI20 Y/M here. config ISDN_CAPI_CAPIFS_BOOL - bool "CAPI2.0 filesystem support" + bool "CAPI2.0 filesystem support (DEPRECATED)" depends on ISDN_CAPI_MIDDLEWARE && ISDN_CAPI_CAPI20 + help + This option provides a special file system, similar to /dev/pts with + device nodes for the special ttys established by using the + middleware extension above. + You no longer need this, udev fully replaces it. This feature is + scheduled for removal. config ISDN_CAPI_CAPIFS tristate depends on ISDN_CAPI_CAPIFS_BOOL default ISDN_CAPI_CAPI20 - help - This option provides a special file system, similar to /dev/pts with - device nodes for the special ttys established by using the - middleware extension above. If you want to use pppd with - pppdcapiplugin to dial up to your ISP, say Y here. config ISDN_CAPI_CAPIDRV tristate "CAPI2.0 capidrv interface support" -- cgit v1.2.2 From 771f4c87be909ad9feb6af26424485b02deed244 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:45 +0000 Subject: CAPI: Remove experimental tag from middleware feature Despite all its bugs, the middleware support of our CAPI stack was already in use for many, many moons. And after going through its code, fixing all issues I found, I feel it deserves to officially become a non-experimental feature. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/capi/Kconfig b/drivers/isdn/capi/Kconfig index d607d465786e..a168e8a891be 100644 --- a/drivers/isdn/capi/Kconfig +++ b/drivers/isdn/capi/Kconfig @@ -17,8 +17,7 @@ config CAPI_TRACE If unsure, say Y. config ISDN_CAPI_MIDDLEWARE - bool "CAPI2.0 Middleware support (EXPERIMENTAL)" - depends on EXPERIMENTAL + bool "CAPI2.0 Middleware support" help This option will enhance the capabilities of the /dev/capi20 interface. It will provide a means of moving a data connection, -- cgit v1.2.2 From e5f8d9ac46e0291594abaa76bf467a08367bcccf Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Mon, 22 Feb 2010 11:09:38 +0000 Subject: isdn: fix a few Kconfig imperfections 1. Rewrite the outdated help texts for config options ISDN and ISDN_CAPI. 2. The MISDN config option appeared between ISDN_I4L and the I4L hardware driver options; move it to a less irritating place. 3. HYSDN is not in fact an I4L driver, and needn't depend on ISDN_I4L, so move it from the I4L section to the general section. 4. ISDN_HDLC is now also used by drivers outside I4L. Move it from the I4L section to the general section, too. Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/Kconfig | 43 ++++++++++++++++++++++++++++--------------- drivers/isdn/i4l/Kconfig | 7 ------- 2 files changed, 28 insertions(+), 22 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig index 022a19452953..4fb601670de3 100644 --- a/drivers/isdn/Kconfig +++ b/drivers/isdn/Kconfig @@ -7,15 +7,14 @@ menuconfig ISDN depends on NET depends on !S390 ---help--- - ISDN ("Integrated Services Digital Networks", called RNIS in France) - is a special type of fully digital telephone service; it's mostly - used to connect to your Internet service provider (with SLIP or - PPP). The main advantage is that the speed is higher than ordinary - modem/telephone connections, and that you can have voice - conversations while downloading stuff. It only works if your - computer is equipped with an ISDN card and both you and your service - provider purchased an ISDN line from the phone company. For - details, read on the WWW. + ISDN ("Integrated Services Digital Network", called RNIS in France) + is a fully digital telephone service that can be used for voice and + data connections. If your computer is equipped with an ISDN + adapter you can use it to connect to your Internet service provider + (with SLIP or PPP) faster than via a conventional telephone modem + (though still much slower than with DSL) or to make and accept + voice calls (eg. turning your PC into a software answering machine + or PABX). Select this option if you want your kernel to support ISDN. @@ -39,17 +38,22 @@ menuconfig ISDN_I4L It is still available, though, for use with adapters that are not supported by the new CAPI subsystem yet. -source "drivers/isdn/mISDN/Kconfig" - source "drivers/isdn/i4l/Kconfig" menuconfig ISDN_CAPI tristate "CAPI 2.0 subsystem" help - This provides the CAPI (Common ISDN Application Programming - Interface, a standard making it easy for programs to access ISDN - hardware, see . This is needed for AVM's set - of active ISDN controllers like B1, T1, M1. + This provides CAPI (the Common ISDN Application Programming + Interface) Version 2.0, a standard making it easy for programs to + access ISDN hardware in a device independent way. (For details see + .) CAPI supports making and accepting voice + and data connections, controlling call options and protocols, + as well as ISDN supplementary services like call forwarding or + three-party conferences (if supported by the specific hardware + driver). + + Select this option and the appropriate hardware driver below if + you have an ISDN adapter supported by the CAPI subsystem. if ISDN_CAPI @@ -61,4 +65,13 @@ endif # ISDN_CAPI source "drivers/isdn/gigaset/Kconfig" +source "drivers/isdn/hysdn/Kconfig" + +source "drivers/isdn/mISDN/Kconfig" + +config ISDN_HDLC + tristate + select CRC_CCITT + select BITREVERSE + endif # ISDN diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig index 07c4e49f9e77..9c6650ea848e 100644 --- a/drivers/isdn/i4l/Kconfig +++ b/drivers/isdn/i4l/Kconfig @@ -134,14 +134,7 @@ source "drivers/isdn/sc/Kconfig" source "drivers/isdn/act2000/Kconfig" -source "drivers/isdn/hysdn/Kconfig" - endmenu # end ISDN_I4L endif -config ISDN_HDLC - tristate - select CRC_CCITT - select BITREVERSE - -- cgit v1.2.2 From 41a68a748bbc61f5bcea999e33ba72926dfbe6f7 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Mon, 18 Jan 2010 17:24:10 +0100 Subject: PCI: push deprecated pci_find_device() function to last user The ISDN4Linux HiSax driver family contains the last remaining users of the deprecated pci_find_device() function. This patch creates a private copy of that function in HiSax, and removes the now unused global function together with its controlling configuration option, CONFIG_PCI_LEGACY. Signed-off-by: Tilman Schmidt Signed-off-by: Jesse Barnes --- drivers/isdn/hisax/Kconfig | 18 +++++++++--------- drivers/isdn/hisax/avm_pci.c | 6 +++--- drivers/isdn/hisax/bkm_a4t.c | 2 +- drivers/isdn/hisax/bkm_a8.c | 2 +- drivers/isdn/hisax/diva.c | 14 +++++++------- drivers/isdn/hisax/elsa.c | 8 ++++---- drivers/isdn/hisax/enternow_pci.c | 2 +- drivers/isdn/hisax/gazel.c | 8 ++++---- drivers/isdn/hisax/hfc_pci.c | 2 +- drivers/isdn/hisax/hisax.h | 23 +++++++++++++++++++++++ drivers/isdn/hisax/niccy.c | 6 +++--- drivers/isdn/hisax/nj_s.c | 2 +- drivers/isdn/hisax/nj_u.c | 2 +- drivers/isdn/hisax/sedlbauer.c | 6 +++--- drivers/isdn/hisax/telespci.c | 2 +- drivers/isdn/hisax/w6692.c | 2 +- 16 files changed, 64 insertions(+), 41 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig index 3464ebc4cdbc..452fde9edf86 100644 --- a/drivers/isdn/hisax/Kconfig +++ b/drivers/isdn/hisax/Kconfig @@ -109,7 +109,7 @@ config HISAX_16_3 config HISAX_TELESPCI bool "Teles PCI" - depends on PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) + depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) help This enables HiSax support for the Teles PCI. See on how to configure it. @@ -237,7 +237,7 @@ config HISAX_MIC config HISAX_NETJET bool "NETjet card" - depends on PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) + depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) help This enables HiSax support for the NetJet from Traverse Technologies. @@ -248,7 +248,7 @@ config HISAX_NETJET config HISAX_NETJET_U bool "NETspider U card" - depends on PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) + depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) help This enables HiSax support for the Netspider U interface ISDN card from Traverse Technologies. @@ -287,7 +287,7 @@ config HISAX_HSTSAPHIR config HISAX_BKM_A4T bool "Telekom A4T card" - depends on PCI && PCI_LEGACY + depends on PCI help This enables HiSax support for the Telekom A4T card. @@ -297,7 +297,7 @@ config HISAX_BKM_A4T config HISAX_SCT_QUADRO bool "Scitel Quadro card" - depends on PCI && PCI_LEGACY + depends on PCI help This enables HiSax support for the Scitel Quadro card. @@ -316,7 +316,7 @@ config HISAX_GAZEL config HISAX_HFC_PCI bool "HFC PCI-Bus cards" - depends on PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) + depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) help This enables HiSax support for the HFC-S PCI 2BDS0 based cards. @@ -325,7 +325,7 @@ config HISAX_HFC_PCI config HISAX_W6692 bool "Winbond W6692 based cards" - depends on PCI && PCI_LEGACY + depends on PCI help This enables HiSax support for Winbond W6692 based PCI ISDN cards. @@ -341,7 +341,7 @@ config HISAX_HFC_SX config HISAX_ENTERNOW_PCI bool "Formula-n enter:now PCI card" - depends on HISAX_NETJET && PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) + depends on HISAX_NETJET && PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) help This enables HiSax support for the Formula-n enter:now PCI ISDN card. @@ -412,7 +412,7 @@ config HISAX_HFC4S8S config HISAX_FRITZ_PCIPNP tristate "AVM Fritz!Card PCI/PCIv2/PnP support (EXPERIMENTAL)" - depends on PCI && PCI_LEGACY && EXPERIMENTAL + depends on PCI && EXPERIMENTAL help This enables the driver for the AVM Fritz!Card PCI, Fritz!Card PCI v2 and Fritz!Card PnP. diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c index 7cabc5a19492..14295a155e71 100644 --- a/drivers/isdn/hisax/avm_pci.c +++ b/drivers/isdn/hisax/avm_pci.c @@ -822,7 +822,7 @@ static int __devinit avm_pnp_setup(struct IsdnCardState *cs) #endif /* __ISAPNP__ */ -#ifndef CONFIG_PCI_LEGACY +#ifndef CONFIG_PCI static int __devinit avm_pci_setup(struct IsdnCardState *cs) { @@ -835,7 +835,7 @@ static struct pci_dev *dev_avm __devinitdata = NULL; static int __devinit avm_pci_setup(struct IsdnCardState *cs) { - if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM, + if ((dev_avm = hisax_find_pci_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1, dev_avm))) { if (pci_enable_device(dev_avm)) @@ -864,7 +864,7 @@ static int __devinit avm_pci_setup(struct IsdnCardState *cs) return (1); } -#endif /* CONFIG_PCI_LEGACY */ +#endif /* CONFIG_PCI */ int __devinit setup_avm_pcipnp(struct IsdnCard *card) diff --git a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c index 9ca2ee54cc94..9f2009c0b69c 100644 --- a/drivers/isdn/hisax/bkm_a4t.c +++ b/drivers/isdn/hisax/bkm_a4t.c @@ -340,7 +340,7 @@ setup_bkm_a4t(struct IsdnCard *card) } else return (0); - while ((dev_a4t = pci_find_device(PCI_VENDOR_ID_ZORAN, + while ((dev_a4t = hisax_find_pci_device(PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) { ret = a4t_pci_probe(dev_a4t, cs, &found, &pci_memaddr); if (!ret) diff --git a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c index e1ff4717a8a6..e775706c60e3 100644 --- a/drivers/isdn/hisax/bkm_a8.c +++ b/drivers/isdn/hisax/bkm_a8.c @@ -301,7 +301,7 @@ setup_sct_quadro(struct IsdnCard *card) (sub_vendor_id != PCI_VENDOR_ID_BERKOM))) return (0); if (cs->subtyp == SCT_1) { - while ((dev_a8 = pci_find_device(PCI_VENDOR_ID_PLX, + while ((dev_a8 = hisax_find_pci_device(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, dev_a8))) { sub_vendor_id = dev_a8->subsystem_vendor; diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c index 0b0c2e5d806b..780da9bda915 100644 --- a/drivers/isdn/hisax/diva.c +++ b/drivers/isdn/hisax/diva.c @@ -1148,7 +1148,7 @@ static int __devinit setup_diva_isapnp(struct IsdnCard *card) #endif /* ISAPNP */ -#ifdef CONFIG_PCI_LEGACY +#ifdef CONFIG_PCI static struct pci_dev *dev_diva __devinitdata = NULL; static struct pci_dev *dev_diva_u __devinitdata = NULL; static struct pci_dev *dev_diva201 __devinitdata = NULL; @@ -1159,21 +1159,21 @@ static int __devinit setup_diva_pci(struct IsdnCard *card) struct IsdnCardState *cs = card->cs; cs->subtyp = 0; - if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON, + if ((dev_diva = hisax_find_pci_device(PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) { if (pci_enable_device(dev_diva)) return(0); cs->subtyp = DIVA_PCI; cs->irq = dev_diva->irq; cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2); - } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON, + } else if ((dev_diva_u = hisax_find_pci_device(PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) { if (pci_enable_device(dev_diva_u)) return(0); cs->subtyp = DIVA_PCI; cs->irq = dev_diva_u->irq; cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2); - } else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON, + } else if ((dev_diva201 = hisax_find_pci_device(PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) { if (pci_enable_device(dev_diva201)) return(0); @@ -1183,7 +1183,7 @@ static int __devinit setup_diva_pci(struct IsdnCard *card) (ulong) ioremap(pci_resource_start(dev_diva201, 0), 4096); cs->hw.diva.cfg_reg = (ulong) ioremap(pci_resource_start(dev_diva201, 1), 4096); - } else if ((dev_diva202 = pci_find_device(PCI_VENDOR_ID_EICON, + } else if ((dev_diva202 = hisax_find_pci_device(PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA202, dev_diva202))) { if (pci_enable_device(dev_diva202)) return(0); @@ -1229,14 +1229,14 @@ static int __devinit setup_diva_pci(struct IsdnCard *card) return (1); /* card found */ } -#else /* if !CONFIG_PCI_LEGACY */ +#else /* if !CONFIG_PCI */ static int __devinit setup_diva_pci(struct IsdnCard *card) { return (-1); /* card not found; continue search */ } -#endif /* CONFIG_PCI_LEGACY */ +#endif /* CONFIG_PCI */ int __devinit setup_diva(struct IsdnCard *card) diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c index aa29d1cf16af..23c41fcd864e 100644 --- a/drivers/isdn/hisax/elsa.c +++ b/drivers/isdn/hisax/elsa.c @@ -1025,7 +1025,7 @@ setup_elsa_pcmcia(struct IsdnCard *card) cs->irq); } -#ifdef CONFIG_PCI_LEGACY +#ifdef CONFIG_PCI static struct pci_dev *dev_qs1000 __devinitdata = NULL; static struct pci_dev *dev_qs3000 __devinitdata = NULL; @@ -1035,7 +1035,7 @@ setup_elsa_pci(struct IsdnCard *card) struct IsdnCardState *cs = card->cs; cs->subtyp = 0; - if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA, + if ((dev_qs1000 = hisax_find_pci_device(PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) { if (pci_enable_device(dev_qs1000)) return(0); @@ -1043,7 +1043,7 @@ setup_elsa_pci(struct IsdnCard *card) cs->irq = dev_qs1000->irq; cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1); cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3); - } else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA, + } else if ((dev_qs3000 = hisax_find_pci_device(PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) { if (pci_enable_device(dev_qs3000)) return(0); @@ -1093,7 +1093,7 @@ setup_elsa_pci(struct IsdnCard *card) { return (1); } -#endif /* CONFIG_PCI_LEGACY */ +#endif /* CONFIG_PCI */ static int __devinit setup_elsa_common(struct IsdnCard *card) diff --git a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c index 39f421ed8de8..26264abf1f58 100644 --- a/drivers/isdn/hisax/enternow_pci.c +++ b/drivers/isdn/hisax/enternow_pci.c @@ -406,7 +406,7 @@ setup_enternow_pci(struct IsdnCard *card) for ( ;; ) { - if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, + if ((dev_netjet = hisax_find_pci_device(PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { ret = en_pci_probe(dev_netjet, cs); if (!ret) diff --git a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c index 0ea3b4607680..353982fc1436 100644 --- a/drivers/isdn/hisax/gazel.c +++ b/drivers/isdn/hisax/gazel.c @@ -531,7 +531,7 @@ setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs) return (0); } -#ifdef CONFIG_PCI_LEGACY +#ifdef CONFIG_PCI static struct pci_dev *dev_tel __devinitdata = NULL; static int __devinit @@ -546,7 +546,7 @@ setup_gazelpci(struct IsdnCardState *cs) found = 0; seekcard = PCI_DEVICE_ID_PLX_R685; for (nbseek = 0; nbseek < 4; nbseek++) { - if ((dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, + if ((dev_tel = hisax_find_pci_device(PCI_VENDOR_ID_PLX, seekcard, dev_tel))) { if (pci_enable_device(dev_tel)) return 1; @@ -620,7 +620,7 @@ setup_gazelpci(struct IsdnCardState *cs) return (0); } -#endif /* CONFIG_PCI_LEGACY */ +#endif /* CONFIG_PCI */ int __devinit setup_gazel(struct IsdnCard *card) @@ -640,7 +640,7 @@ setup_gazel(struct IsdnCard *card) return (0); } else { -#ifdef CONFIG_PCI_LEGACY +#ifdef CONFIG_PCI if (setup_gazelpci(cs)) return (0); #else diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c index 10914731b304..917cc84065bd 100644 --- a/drivers/isdn/hisax/hfc_pci.c +++ b/drivers/isdn/hisax/hfc_pci.c @@ -1658,7 +1658,7 @@ setup_hfcpci(struct IsdnCard *card) i = 0; while (id_list[i].vendor_id) { - tmp_hfcpci = pci_find_device(id_list[i].vendor_id, + tmp_hfcpci = hisax_find_pci_device(id_list[i].vendor_id, id_list[i].device_id, dev_hfcpci); i++; diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h index 0685c1946969..832a87855ffb 100644 --- a/drivers/isdn/hisax/hisax.h +++ b/drivers/isdn/hisax/hisax.h @@ -1323,3 +1323,26 @@ void release_tei(struct IsdnCardState *cs); char *HiSax_getrev(const char *revision); int TeiNew(void); void TeiFree(void); + +#ifdef CONFIG_PCI + +#include + +/* adaptation wrapper for old usage + * WARNING! This is unfit for use in a PCI hotplug environment, + * as the returned PCI device can disappear at any moment in time. + * Callers should be converted to use pci_get_device() instead. + */ +static inline struct pci_dev *hisax_find_pci_device(unsigned int vendor, + unsigned int device, + struct pci_dev *from) +{ + struct pci_dev *pdev; + + pci_dev_get(from); + pdev = pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from); + pci_dev_put(pdev); + return pdev; +} + +#endif diff --git a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c index ef00633e1d2a..ccaa6e13310f 100644 --- a/drivers/isdn/hisax/niccy.c +++ b/drivers/isdn/hisax/niccy.c @@ -297,12 +297,12 @@ int __devinit setup_niccy(struct IsdnCard *card) return 0; } } else { -#ifdef CONFIG_PCI_LEGACY +#ifdef CONFIG_PCI static struct pci_dev *niccy_dev __devinitdata; u_int pci_ioaddr; cs->subtyp = 0; - if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM, + if ((niccy_dev = hisax_find_pci_device(PCI_VENDOR_ID_SATSAGEM, PCI_DEVICE_ID_SATSAGEM_NICCY, niccy_dev))) { if (pci_enable_device(niccy_dev)) @@ -354,7 +354,7 @@ int __devinit setup_niccy(struct IsdnCard *card) printk(KERN_WARNING "Niccy: io0 0 and NO_PCI_BIOS\n"); printk(KERN_WARNING "Niccy: unable to config NICCY PCI\n"); return 0; -#endif /* CONFIG_PCI_LEGACY */ +#endif /* CONFIG_PCI */ } printk(KERN_INFO "HiSax: NICCY %s config irq:%d data:0x%X ale:0x%X\n", (cs->subtyp == 1) ? "PnP" : "PCI", diff --git a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c index 8d36ccc87d81..2344e7b33448 100644 --- a/drivers/isdn/hisax/nj_s.c +++ b/drivers/isdn/hisax/nj_s.c @@ -276,7 +276,7 @@ setup_netjet_s(struct IsdnCard *card) for ( ;; ) { - if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, + if ((dev_netjet = hisax_find_pci_device(PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { ret = njs_pci_probe(dev_netjet, cs); if (!ret) diff --git a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c index d306c946ffba..095e974aed80 100644 --- a/drivers/isdn/hisax/nj_u.c +++ b/drivers/isdn/hisax/nj_u.c @@ -240,7 +240,7 @@ setup_netjet_u(struct IsdnCard *card) for ( ;; ) { - if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, + if ((dev_netjet = hisax_find_pci_device(PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { ret = nju_pci_probe(dev_netjet, cs); if (!ret) diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c index 5569a522e2a1..69dfc8d29017 100644 --- a/drivers/isdn/hisax/sedlbauer.c +++ b/drivers/isdn/hisax/sedlbauer.c @@ -598,7 +598,7 @@ setup_sedlbauer_isapnp(struct IsdnCard *card, int *bytecnt) } #endif /* __ISAPNP__ */ -#ifdef CONFIG_PCI_LEGACY +#ifdef CONFIG_PCI static struct pci_dev *dev_sedl __devinitdata = NULL; static int __devinit @@ -607,7 +607,7 @@ setup_sedlbauer_pci(struct IsdnCard *card) struct IsdnCardState *cs = card->cs; u16 sub_vendor_id, sub_id; - if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET, + if ((dev_sedl = hisax_find_pci_device(PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) { if (pci_enable_device(dev_sedl)) return(0); @@ -673,7 +673,7 @@ setup_sedlbauer_pci(struct IsdnCard *card) return (1); } -#endif /* CONFIG_PCI_LEGACY */ +#endif /* CONFIG_PCI */ int __devinit setup_sedlbauer(struct IsdnCard *card) diff --git a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c index 28b08de4673d..b85ceb3746ce 100644 --- a/drivers/isdn/hisax/telespci.c +++ b/drivers/isdn/hisax/telespci.c @@ -300,7 +300,7 @@ setup_telespci(struct IsdnCard *card) if (cs->typ != ISDN_CTYPE_TELESPCI) return (0); - if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) { + if ((dev_tel = hisax_find_pci_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) { if (pci_enable_device(dev_tel)) return(0); cs->irq = dev_tel->irq; diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c index c4d862c11a60..9d6e864023fe 100644 --- a/drivers/isdn/hisax/w6692.c +++ b/drivers/isdn/hisax/w6692.c @@ -1007,7 +1007,7 @@ setup_w6692(struct IsdnCard *card) return (0); while (id_list[id_idx].vendor_id) { - dev_w6692 = pci_find_device(id_list[id_idx].vendor_id, + dev_w6692 = hisax_find_pci_device(id_list[id_idx].vendor_id, id_list[id_idx].device_id, dev_w6692); if (dev_w6692) { -- cgit v1.2.2 From 63e055d1c6e3a5f6d370cc841d621d5fa4d5d834 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Mon, 22 Feb 2010 13:09:22 +0000 Subject: bas_gigaset: collapse CR/LF at end of AT response Copy the mechanism from ser_/usb_gigaset to avoid producing spurious empty responses for CR/LF sequences from the device. Add a comment in all drivers documenting that behaviour. Correct an off by one error that might result in a one byte buffer overflow when receiving an unexpectedly long reply. Impact: minor bugfix Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/asyncdata.c | 2 ++ drivers/isdn/gigaset/gigaset.h | 4 ++-- drivers/isdn/gigaset/isocdata.c | 44 ++++++++++++++++++++++++++++------------ 3 files changed, 35 insertions(+), 15 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index ccb2a7b7c41d..e913beb63f24 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c @@ -40,6 +40,8 @@ static inline int muststuff(unsigned char c) * Append received bytes to the command response buffer and forward them * line by line to the response handler. Exit whenever a mode/state change * might have occurred. + * Note: Received lines may be terminated by CR, LF, or CR LF, which will be + * removed before passing the line to the response handler. * Return value: * number of processed bytes */ diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index e963a6c2e86d..c9ccf7de2275 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -38,7 +38,7 @@ #define GIG_COMPAT {0, 4, 0, 0} #define MAX_REC_PARAMS 10 /* Max. number of params in response string */ -#define MAX_RESP_SIZE 512 /* Max. size of a response string */ +#define MAX_RESP_SIZE 511 /* Max. size of a response string */ #define MAX_EVENTS 64 /* size of event queue */ @@ -498,7 +498,7 @@ struct cardstate { spinlock_t ev_lock; /* current modem response */ - unsigned char respdata[MAX_RESP_SIZE]; + unsigned char respdata[MAX_RESP_SIZE+1]; unsigned cbytes; /* private data of hardware drivers */ diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index 85394a6ebae8..16fd3bd48883 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c @@ -905,29 +905,49 @@ void gigaset_isoc_receive(unsigned char *src, unsigned count, /* == data input =========================================================== */ +/* process a block of received bytes in command mode (mstate != MS_LOCKED) + * Append received bytes to the command response buffer and forward them + * line by line to the response handler. + * Note: Received lines may be terminated by CR, LF, or CR LF, which will be + * removed before passing the line to the response handler. + */ static void cmd_loop(unsigned char *src, int numbytes, struct inbuf_t *inbuf) { struct cardstate *cs = inbuf->cs; unsigned cbytes = cs->cbytes; + unsigned char c; while (numbytes--) { - /* copy next character, check for end of line */ - switch (cs->respdata[cbytes] = *src++) { - case '\r': + c = *src++; + switch (c) { case '\n': - /* end of line */ - gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)", - __func__, cbytes); - if (cbytes >= MAX_RESP_SIZE - 1) - dev_warn(cs->dev, "response too large\n"); + if (cbytes == 0 && cs->respdata[0] == '\r') { + /* collapse LF with preceding CR */ + cs->respdata[0] = 0; + break; + } + /* --v-- fall through --v-- */ + case '\r': + /* end of message line, pass to response handler */ + if (cbytes >= MAX_RESP_SIZE) { + dev_warn(cs->dev, "response too large (%d)\n", + cbytes); + cbytes = MAX_RESP_SIZE; + } cs->cbytes = cbytes; + gigaset_dbg_buffer(DEBUG_TRANSCMD, "received response", + cbytes, cs->respdata); gigaset_handle_modem_response(cs); cbytes = 0; + + /* store EOL byte for CRLF collapsing */ + cs->respdata[0] = c; break; default: - /* advance in line buffer, checking for overflow */ - if (cbytes < MAX_RESP_SIZE - 1) - cbytes++; + /* append to line buffer if possible */ + if (cbytes < MAX_RESP_SIZE) + cs->respdata[cbytes] = c; + cbytes++; } } @@ -958,8 +978,6 @@ void gigaset_isoc_input(struct inbuf_t *inbuf) numbytes, src); gigaset_if_receive(inbuf->cs, src, numbytes); } else { - gigaset_dbg_buffer(DEBUG_CMD, "received response", - numbytes, src); cmd_loop(src, numbytes, inbuf); } -- cgit v1.2.2 From 1528b18f7ec2b907711f37667c68e10d9296c882 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Mon, 22 Feb 2010 13:09:52 +0000 Subject: gigaset: reduce syslog clutter Improve readability of the Gigaset driver's kernel messages by removing a few unnecessary messages and limiting the emission of some debug messages more narrowly. Impact: logging Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/asyncdata.c | 4 +-- drivers/isdn/gigaset/bas-gigaset.c | 18 ++++------- drivers/isdn/gigaset/capi.c | 15 +++------ drivers/isdn/gigaset/common.c | 49 ++++++++++++----------------- drivers/isdn/gigaset/ev-layer.c | 63 +++++++++++++++++++------------------- drivers/isdn/gigaset/gigaset.h | 7 ++--- drivers/isdn/gigaset/i4l.c | 52 ++++--------------------------- drivers/isdn/gigaset/interface.c | 12 +++----- drivers/isdn/gigaset/proc.c | 2 -- drivers/isdn/gigaset/usb-gigaset.c | 2 +- 10 files changed, 77 insertions(+), 147 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index e913beb63f24..c5016bd2d94f 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c @@ -67,14 +67,14 @@ static unsigned cmd_loop(unsigned numbytes, struct inbuf_t *inbuf) /* --v-- fall through --v-- */ case '\r': /* end of message line, pass to response handler */ - gig_dbg(DEBUG_TRANSCMD, "%s: End of Message (%d Bytes)", - __func__, cbytes); if (cbytes >= MAX_RESP_SIZE) { dev_warn(cs->dev, "response too large (%d)\n", cbytes); cbytes = MAX_RESP_SIZE; } cs->cbytes = cbytes; + gigaset_dbg_buffer(DEBUG_TRANSCMD, "received response", + cbytes, cs->respdata); gigaset_handle_modem_response(cs); cbytes = 0; diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 95ebc5129895..0be15c70c16d 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -347,12 +347,7 @@ static inline void error_hangup(struct bc_state *bcs) { struct cardstate *cs = bcs->cs; - gig_dbg(DEBUG_ANY, "%s: scheduling HUP for channel %d", - __func__, bcs->channel); - - if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) - dev_err(cs->dev, "event queue full\n"); - + gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL); gigaset_schedule_event(cs); } @@ -1706,8 +1701,7 @@ static void complete_cb(struct cardstate *cs) /* unqueue completed buffer */ cs->cmdbytes -= cs->curlen; - gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, - "write_command: sent %u bytes, %u left", + gig_dbg(DEBUG_OUTPUT, "write_command: sent %u bytes, %u left", cs->curlen, cs->cmdbytes); if (cb->next != NULL) { cs->cmdbuf = cb->next; @@ -1881,13 +1875,13 @@ static int start_cbsend(struct cardstate *cs) /* check if suspend requested */ if (ucs->basstate & BS_SUSPEND) { - gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "suspending"); + gig_dbg(DEBUG_OUTPUT, "suspending"); return -EHOSTUNREACH; } /* check if AT channel is open */ if (!(ucs->basstate & BS_ATOPEN)) { - gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "AT channel not open"); + gig_dbg(DEBUG_OUTPUT, "AT channel not open"); rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT); if (rc < 0) { /* flush command queue */ @@ -2251,7 +2245,7 @@ static int gigaset_probe(struct usb_interface *interface, int i, j; int rc; - gig_dbg(DEBUG_ANY, + gig_dbg(DEBUG_INIT, "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", __func__, le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idProduct)); @@ -2259,7 +2253,7 @@ static int gigaset_probe(struct usb_interface *interface, /* set required alternate setting */ hostif = interface->cur_altsetting; if (hostif->desc.bAlternateSetting != 3) { - gig_dbg(DEBUG_ANY, + gig_dbg(DEBUG_INIT, "%s: wrong alternate setting %d - trying to switch", __func__, hostif->desc.bAlternateSetting); if (usb_set_interface(udev, hostif->desc.bInterfaceNumber, 3) diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index 6f0ae32906bf..20ebcee9b0c0 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -1427,9 +1427,10 @@ static void do_connect_req(struct gigaset_capi_ctr *iif, /* queue & schedule EV_DIAL event */ if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, commands, - bcs->at_state.seq_index, NULL)) - goto oom; - gig_dbg(DEBUG_CMD, "scheduling DIAL"); + bcs->at_state.seq_index, NULL)) { + info = CAPI_MSGOSRESOURCEERR; + goto error; + } gigaset_schedule_event(cs); ap->connected = APCONN_SETUP; send_conf(iif, ap, skb, CapiSuccess); @@ -1543,7 +1544,6 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif, if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state, EV_ACCEPT, NULL, 0, NULL)) return; - gig_dbg(DEBUG_CMD, "scheduling ACCEPT"); gigaset_schedule_event(cs); return; @@ -1584,7 +1584,6 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif, if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state, EV_HUP, NULL, 0, NULL)) return; - gig_dbg(DEBUG_CMD, "scheduling HUP"); gigaset_schedule_event(cs); return; } @@ -1667,11 +1666,9 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif, /* trigger hangup, causing eventual DISCONNECT_IND */ if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) { - dev_err(cs->dev, "%s: out of memory\n", __func__); dev_kfree_skb_any(skb); return; } - gig_dbg(DEBUG_CMD, "scheduling HUP"); gigaset_schedule_event(cs); /* emit DISCONNECT_B3_IND */ @@ -1770,11 +1767,9 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif, /* trigger hangup, causing eventual DISCONNECT_IND */ if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) { - dev_err(cs->dev, "%s: out of memory\n", __func__); send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); return; } - gig_dbg(DEBUG_CMD, "scheduling HUP"); gigaset_schedule_event(cs); /* emit reply */ @@ -1817,11 +1812,9 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif, /* trigger hangup, causing eventual DISCONNECT_B3_IND */ if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state, EV_HUP, NULL, 0, NULL)) { - dev_err(cs->dev, "%s: out of memory\n", __func__); send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); return; } - gig_dbg(DEBUG_CMD, "scheduling HUP"); gigaset_schedule_event(cs); /* NCPI parameter: not applicable for B3 Transparent */ diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 664b0c519c3e..85de3399a2f2 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -149,10 +149,8 @@ static int test_timeout(struct at_state_t *at_state) return 0; } - if (!gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL, - at_state->timer_index, NULL)) - dev_err(at_state->cs->dev, "%s: out of memory\n", - __func__); + gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL, + at_state->timer_index, NULL); return 1; } @@ -180,7 +178,7 @@ static void timer_tick(unsigned long data) if (cs->running) { mod_timer(&cs->timer, jiffies + msecs_to_jiffies(GIG_TICK)); if (timeout) { - gig_dbg(DEBUG_CMD, "scheduling timeout"); + gig_dbg(DEBUG_EVENT, "scheduling timeout"); tasklet_schedule(&cs->event_tasklet); } } @@ -194,14 +192,14 @@ int gigaset_get_channel(struct bc_state *bcs) spin_lock_irqsave(&bcs->cs->lock, flags); if (bcs->use_count || !try_module_get(bcs->cs->driver->owner)) { - gig_dbg(DEBUG_ANY, "could not allocate channel %d", + gig_dbg(DEBUG_CHANNEL, "could not allocate channel %d", bcs->channel); spin_unlock_irqrestore(&bcs->cs->lock, flags); return 0; } ++bcs->use_count; bcs->busy = 1; - gig_dbg(DEBUG_ANY, "allocated channel %d", bcs->channel); + gig_dbg(DEBUG_CHANNEL, "allocated channel %d", bcs->channel); spin_unlock_irqrestore(&bcs->cs->lock, flags); return 1; } @@ -213,7 +211,7 @@ struct bc_state *gigaset_get_free_channel(struct cardstate *cs) spin_lock_irqsave(&cs->lock, flags); if (!try_module_get(cs->driver->owner)) { - gig_dbg(DEBUG_ANY, + gig_dbg(DEBUG_CHANNEL, "could not get module for allocating channel"); spin_unlock_irqrestore(&cs->lock, flags); return NULL; @@ -223,12 +221,12 @@ struct bc_state *gigaset_get_free_channel(struct cardstate *cs) ++cs->bcs[i].use_count; cs->bcs[i].busy = 1; spin_unlock_irqrestore(&cs->lock, flags); - gig_dbg(DEBUG_ANY, "allocated channel %d", i); + gig_dbg(DEBUG_CHANNEL, "allocated channel %d", i); return cs->bcs + i; } module_put(cs->driver->owner); spin_unlock_irqrestore(&cs->lock, flags); - gig_dbg(DEBUG_ANY, "no free channel"); + gig_dbg(DEBUG_CHANNEL, "no free channel"); return NULL; } @@ -238,14 +236,15 @@ void gigaset_free_channel(struct bc_state *bcs) spin_lock_irqsave(&bcs->cs->lock, flags); if (!bcs->busy) { - gig_dbg(DEBUG_ANY, "could not free channel %d", bcs->channel); + gig_dbg(DEBUG_CHANNEL, "could not free channel %d", + bcs->channel); spin_unlock_irqrestore(&bcs->cs->lock, flags); return; } --bcs->use_count; bcs->busy = 0; module_put(bcs->cs->driver->owner); - gig_dbg(DEBUG_ANY, "freed channel %d", bcs->channel); + gig_dbg(DEBUG_CHANNEL, "freed channel %d", bcs->channel); spin_unlock_irqrestore(&bcs->cs->lock, flags); } @@ -258,14 +257,15 @@ int gigaset_get_channels(struct cardstate *cs) for (i = 0; i < cs->channels; ++i) if (cs->bcs[i].use_count) { spin_unlock_irqrestore(&cs->lock, flags); - gig_dbg(DEBUG_ANY, "could not allocate all channels"); + gig_dbg(DEBUG_CHANNEL, + "could not allocate all channels"); return 0; } for (i = 0; i < cs->channels; ++i) ++cs->bcs[i].use_count; spin_unlock_irqrestore(&cs->lock, flags); - gig_dbg(DEBUG_ANY, "allocated all channels"); + gig_dbg(DEBUG_CHANNEL, "allocated all channels"); return 1; } @@ -275,7 +275,7 @@ void gigaset_free_channels(struct cardstate *cs) unsigned long flags; int i; - gig_dbg(DEBUG_ANY, "unblocking all channels"); + gig_dbg(DEBUG_CHANNEL, "unblocking all channels"); spin_lock_irqsave(&cs->lock, flags); for (i = 0; i < cs->channels; ++i) --cs->bcs[i].use_count; @@ -287,7 +287,7 @@ void gigaset_block_channels(struct cardstate *cs) unsigned long flags; int i; - gig_dbg(DEBUG_ANY, "blocking all channels"); + gig_dbg(DEBUG_CHANNEL, "blocking all channels"); spin_lock_irqsave(&cs->lock, flags); for (i = 0; i < cs->channels; ++i) ++cs->bcs[i].use_count; @@ -338,6 +338,8 @@ struct event_t *gigaset_add_event(struct cardstate *cs, unsigned next, tail; struct event_t *event = NULL; + gig_dbg(DEBUG_EVENT, "queueing event %d", type); + spin_lock_irqsave(&cs->ev_lock, flags); tail = cs->ev_tail; @@ -934,11 +936,8 @@ int gigaset_start(struct cardstate *cs) if (!gigaset_add_event(cs, &cs->at_state, EV_START, NULL, 0, NULL)) { cs->waiting = 0; - dev_err(cs->dev, "%s: out of memory\n", __func__); goto error; } - - gig_dbg(DEBUG_CMD, "scheduling START"); gigaset_schedule_event(cs); wait_event(cs->waitqueue, !cs->waiting); @@ -973,12 +972,8 @@ int gigaset_shutdown(struct cardstate *cs) cs->waiting = 1; - if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) { - dev_err(cs->dev, "%s: out of memory\n", __func__); + if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) goto exit; - } - - gig_dbg(DEBUG_CMD, "scheduling SHUTDOWN"); gigaset_schedule_event(cs); wait_event(cs->waitqueue, !cs->waiting); @@ -1004,12 +999,8 @@ void gigaset_stop(struct cardstate *cs) cs->waiting = 1; - if (!gigaset_add_event(cs, &cs->at_state, EV_STOP, NULL, 0, NULL)) { - dev_err(cs->dev, "%s: out of memory\n", __func__); + if (!gigaset_add_event(cs, &cs->at_state, EV_STOP, NULL, 0, NULL)) goto exit; - } - - gig_dbg(DEBUG_CMD, "scheduling STOP"); gigaset_schedule_event(cs); wait_event(cs->waitqueue, !cs->waiting); diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index ddeb0456d202..c8f89b78b233 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c @@ -427,7 +427,7 @@ static int isdn_getnum(char *p) { int v = -1; - gig_dbg(DEBUG_TRANSCMD, "string: %s", p); + gig_dbg(DEBUG_EVENT, "string: %s", p); while (*p >= '0' && *p <= '9') v = ((v < 0) ? 0 : (v * 10)) + (int) ((*p++) - '0'); @@ -444,7 +444,7 @@ static int isdn_gethex(char *p) int v = 0; int c; - gig_dbg(DEBUG_TRANSCMD, "string: %s", p); + gig_dbg(DEBUG_EVENT, "string: %s", p); if (!*p) return -1; @@ -517,7 +517,6 @@ void gigaset_handle_modem_response(struct cardstate *cs) return; } cs->respdata[len] = 0; - gig_dbg(DEBUG_TRANSCMD, "raw string: '%s'", cs->respdata); argv[0] = cs->respdata; params = 1; if (cs->at_state.getstring) { @@ -552,14 +551,14 @@ void gigaset_handle_modem_response(struct cardstate *cs) for (j = 1; j < params; ++j) argv[j][-1] = 0; - gig_dbg(DEBUG_TRANSCMD, "CMD received: %s", argv[0]); + gig_dbg(DEBUG_EVENT, "CMD received: %s", argv[0]); if (cid) { --params; - gig_dbg(DEBUG_TRANSCMD, "CID: %s", argv[params]); + gig_dbg(DEBUG_EVENT, "CID: %s", argv[params]); } - gig_dbg(DEBUG_TRANSCMD, "available params: %d", params - 1); + gig_dbg(DEBUG_EVENT, "available params: %d", params - 1); for (j = 1; j < params; j++) - gig_dbg(DEBUG_TRANSCMD, "param %d: %s", j, argv[j]); + gig_dbg(DEBUG_EVENT, "param %d: %s", j, argv[j]); } spin_lock_irqsave(&cs->ev_lock, flags); @@ -642,7 +641,7 @@ void gigaset_handle_modem_response(struct cardstate *cs) dev_err(cs->dev, "out of memory\n"); ++curarg; } - gig_dbg(DEBUG_CMD, "string==%s", + gig_dbg(DEBUG_EVENT, "string==%s", event->ptr ? (char *) event->ptr : "NULL"); break; case RT_ZCAU: @@ -669,7 +668,7 @@ void gigaset_handle_modem_response(struct cardstate *cs) ++curarg; } else event->parameter = -1; - gig_dbg(DEBUG_CMD, "parameter==%d", event->parameter); + gig_dbg(DEBUG_EVENT, "parameter==%d", event->parameter); break; } @@ -684,7 +683,7 @@ void gigaset_handle_modem_response(struct cardstate *cs) spin_unlock_irqrestore(&cs->ev_lock, flags); if (curarg != params) - gig_dbg(DEBUG_ANY, + gig_dbg(DEBUG_EVENT, "invalid number of processed parameters: %d/%d", curarg, params); } @@ -705,8 +704,8 @@ static void disconnect(struct at_state_t **at_state_p) /* revert to selected idle mode */ if (!cs->cidmode) { cs->at_state.pending_commands |= PC_UMMODE; + gig_dbg(DEBUG_EVENT, "Scheduling PC_UMMODE"); cs->commands_pending = 1; - gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); } spin_unlock_irqrestore(&cs->lock, flags); @@ -784,15 +783,15 @@ static void init_failed(struct cardstate *cs, int mode) static void schedule_init(struct cardstate *cs, int state) { if (cs->at_state.pending_commands & PC_INIT) { - gig_dbg(DEBUG_CMD, "not scheduling PC_INIT again"); + gig_dbg(DEBUG_EVENT, "not scheduling PC_INIT again"); return; } cs->mstate = state; cs->mode = M_UNKNOWN; gigaset_block_channels(cs); cs->at_state.pending_commands |= PC_INIT; + gig_dbg(DEBUG_EVENT, "Scheduling PC_INIT"); cs->commands_pending = 1; - gig_dbg(DEBUG_CMD, "Scheduling PC_INIT"); } /* Add "AT" to a command, add the cid, dle encode it, send the result to the @@ -923,7 +922,7 @@ static void start_dial(struct at_state_t *at_state, void *data, } at_state->pending_commands |= PC_CID; - gig_dbg(DEBUG_CMD, "Scheduling PC_CID"); + gig_dbg(DEBUG_EVENT, "Scheduling PC_CID"); cs->commands_pending = 1; return; @@ -933,7 +932,7 @@ error: commands[i] = NULL; } at_state->pending_commands |= PC_NOCID; - gig_dbg(DEBUG_CMD, "Scheduling PC_NOCID"); + gig_dbg(DEBUG_EVENT, "Scheduling PC_NOCID"); cs->commands_pending = 1; return; } @@ -955,7 +954,7 @@ static void start_accept(struct at_state_t *at_state) dev_err(at_state->cs->dev, "out of memory\n"); /* error reset */ at_state->pending_commands |= PC_HUP; - gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); + gig_dbg(DEBUG_EVENT, "Scheduling PC_HUP"); cs->commands_pending = 1; return; } @@ -964,7 +963,7 @@ static void start_accept(struct at_state_t *at_state) snprintf(bcs->commands[AT_ISO], 9, "^SISO=%u\r", bcs->channel + 1); at_state->pending_commands |= PC_ACCEPT; - gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT"); + gig_dbg(DEBUG_EVENT, "Scheduling PC_ACCEPT"); cs->commands_pending = 1; } @@ -1009,8 +1008,8 @@ static void do_shutdown(struct cardstate *cs) if (cs->mstate == MS_READY) { cs->mstate = MS_SHUTDOWN; cs->at_state.pending_commands |= PC_SHUTDOWN; + gig_dbg(DEBUG_EVENT, "Scheduling PC_SHUTDOWN"); cs->commands_pending = 1; - gig_dbg(DEBUG_CMD, "Scheduling PC_SHUTDOWN"); } else finish_shutdown(cs); } @@ -1191,8 +1190,8 @@ static void do_action(int action, struct cardstate *cs, } spin_unlock_irqrestore(&cs->lock, flags); cs->at_state.pending_commands |= PC_CIDMODE; + gig_dbg(DEBUG_EVENT, "Scheduling PC_CIDMODE"); cs->commands_pending = 1; - gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); break; case ACT_FAILINIT: dev_warn(cs->dev, "Could not initialize the device.\n"); @@ -1443,7 +1442,7 @@ static void do_action(int action, struct cardstate *cs, case ACT_GOTVER: if (cs->gotfwver == 0) { cs->gotfwver = 1; - gig_dbg(DEBUG_ANY, + gig_dbg(DEBUG_EVENT, "firmware version %02d.%03d.%02d.%02d", cs->fwver[0], cs->fwver[1], cs->fwver[2], cs->fwver[3]); @@ -1481,8 +1480,8 @@ static void do_action(int action, struct cardstate *cs, break; case ACT_HUP: at_state->pending_commands |= PC_HUP; + gig_dbg(DEBUG_EVENT, "Scheduling PC_HUP"); cs->commands_pending = 1; - gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); break; /* hotplug events */ @@ -1519,10 +1518,10 @@ static void do_action(int action, struct cardstate *cs, cs->cidmode = ev->parameter; if (ev->parameter) { cs->at_state.pending_commands |= PC_CIDMODE; - gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); + gig_dbg(DEBUG_EVENT, "Scheduling PC_CIDMODE"); } else { cs->at_state.pending_commands |= PC_UMMODE; - gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); + gig_dbg(DEBUG_EVENT, "Scheduling PC_UMMODE"); } cs->commands_pending = 1; } @@ -1573,6 +1572,8 @@ static void process_event(struct cardstate *cs, struct event_t *ev) if (ev->cid >= 0) { at_state = at_state_from_cid(cs, ev->cid); if (!at_state) { + gig_dbg(DEBUG_EVENT, "event %d for invalid cid %d", + ev->type, ev->cid); gigaset_add_event(cs, &cs->at_state, RSP_WRONG_CID, NULL, 0, NULL); return; @@ -1580,13 +1581,13 @@ static void process_event(struct cardstate *cs, struct event_t *ev) } else { at_state = ev->at_state; if (at_state_invalid(cs, at_state)) { - gig_dbg(DEBUG_ANY, "event for invalid at_state %p", + gig_dbg(DEBUG_EVENT, "event for invalid at_state %p", at_state); return; } } - gig_dbg(DEBUG_CMD, "connection state %d, event %d", + gig_dbg(DEBUG_EVENT, "connection state %d, event %d", at_state->ConState, ev->type); bcs = at_state->bcs; @@ -1600,11 +1601,11 @@ static void process_event(struct cardstate *cs, struct event_t *ev) if (ev->parameter != at_state->timer_index || !at_state->timer_active) { ev->type = RSP_NONE; /* old timeout */ - gig_dbg(DEBUG_ANY, "old timeout"); + gig_dbg(DEBUG_EVENT, "old timeout"); } else if (!at_state->waiting) - gig_dbg(DEBUG_ANY, "timeout occurred"); + gig_dbg(DEBUG_EVENT, "timeout occurred"); else - gig_dbg(DEBUG_ANY, "stopped waiting"); + gig_dbg(DEBUG_EVENT, "stopped waiting"); } spin_unlock_irqrestore(&cs->lock, flags); @@ -1712,11 +1713,11 @@ static void process_command_flags(struct cardstate *cs) cs->commands_pending = 0; if (cs->cur_at_seq) { - gig_dbg(DEBUG_CMD, "not searching scheduled commands: busy"); + gig_dbg(DEBUG_EVENT, "not searching scheduled commands: busy"); return; } - gig_dbg(DEBUG_CMD, "searching scheduled commands"); + gig_dbg(DEBUG_EVENT, "searching scheduled commands"); sequence = SEQ_NONE; @@ -1857,7 +1858,7 @@ static void process_command_flags(struct cardstate *cs) switch (cs->mode) { case M_UNIMODEM: cs->at_state.pending_commands |= PC_CIDMODE; - gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); + gig_dbg(DEBUG_EVENT, "Scheduling PC_CIDMODE"); cs->commands_pending = 1; return; #ifdef GIG_MAYINITONDIAL diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index c9ccf7de2275..1875ab80b335 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -78,9 +78,10 @@ enum debuglevel { DEBUG_STREAM = 0x00040, /* application data stream I/O events */ DEBUG_STREAM_DUMP = 0x00080, /* application data stream content */ DEBUG_LLDATA = 0x00100, /* sent/received LL data */ + DEBUG_EVENT = 0x00200, /* event processing */ DEBUG_DRIVER = 0x00400, /* driver structure */ DEBUG_HDLC = 0x00800, /* M10x HDLC processing */ - DEBUG_WRITE = 0x01000, /* M105 data write */ + DEBUG_CHANNEL = 0x01000, /* channel allocation/deallocation */ DEBUG_TRANSCMD = 0x02000, /* AT-COMMANDS+RESPONSES */ DEBUG_MCMD = 0x04000, /* COMMANDS THAT ARE SENT VERY OFTEN */ DEBUG_INIT = 0x08000, /* (de)allocation+initialization of data @@ -785,8 +786,6 @@ static inline void gigaset_schedule_event(struct cardstate *cs) static inline void gigaset_bchannel_down(struct bc_state *bcs) { gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_CLOSED, NULL, 0, NULL); - - gig_dbg(DEBUG_CMD, "scheduling BC_CLOSED"); gigaset_schedule_event(bcs->cs); } @@ -795,8 +794,6 @@ static inline void gigaset_bchannel_down(struct bc_state *bcs) static inline void gigaset_bchannel_up(struct bc_state *bcs) { gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_OPEN, NULL, 0, NULL); - - gig_dbg(DEBUG_CMD, "scheduling BC_OPEN"); gigaset_schedule_event(bcs->cs); } diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c index c129ee47a8fb..f0acb9dc9e33 100644 --- a/drivers/isdn/gigaset/i4l.c +++ b/drivers/isdn/gigaset/i4l.c @@ -216,7 +216,7 @@ static int command_from_LL(isdn_ctrl *cntrl) return -EINVAL; case ISDN_CMD_DIAL: - gig_dbg(DEBUG_ANY, + gig_dbg(DEBUG_CMD, "ISDN_CMD_DIAL (phone: %s, msn: %s, si1: %d, si2: %d)", cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn, cntrl->parm.setup.si1, cntrl->parm.setup.si2); @@ -304,11 +304,10 @@ static int command_from_LL(isdn_ctrl *cntrl) gigaset_free_channel(bcs); return -ENOMEM; } - - gig_dbg(DEBUG_CMD, "scheduling DIAL"); gigaset_schedule_event(cs); break; case ISDN_CMD_ACCEPTD: + gig_dbg(DEBUG_CMD, "ISDN_CMD_ACCEPTD"); if (ch >= cs->channels) { dev_err(cs->dev, "ISDN_CMD_ACCEPTD: invalid channel (%d)\n", ch); @@ -318,14 +317,11 @@ static int command_from_LL(isdn_ctrl *cntrl) if (!gigaset_add_event(cs, &bcs->at_state, EV_ACCEPT, NULL, 0, NULL)) return -ENOMEM; - - gig_dbg(DEBUG_CMD, "scheduling ACCEPT"); gigaset_schedule_event(cs); - break; - case ISDN_CMD_ACCEPTB: break; case ISDN_CMD_HANGUP: + gig_dbg(DEBUG_CMD, "ISDN_CMD_HANGUP"); if (ch >= cs->channels) { dev_err(cs->dev, "ISDN_CMD_HANGUP: invalid channel (%d)\n", ch); @@ -335,8 +331,6 @@ static int command_from_LL(isdn_ctrl *cntrl) if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) return -ENOMEM; - - gig_dbg(DEBUG_CMD, "scheduling HUP"); gigaset_schedule_event(cs); break; @@ -376,6 +370,7 @@ static int command_from_LL(isdn_ctrl *cntrl) } break; case ISDN_CMD_SETL3: /* Set L3 to given protocol */ + gig_dbg(DEBUG_CMD, "ISDN_CMD_SETL3"); if (ch >= cs->channels) { dev_err(cs->dev, "ISDN_CMD_SETL3: invalid channel (%d)\n", ch); @@ -390,44 +385,9 @@ static int command_from_LL(isdn_ctrl *cntrl) } break; - case ISDN_CMD_PROCEED: - gig_dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); - break; - case ISDN_CMD_ALERT: - gig_dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); - if (cntrl->arg >= cs->channels) { - dev_err(cs->dev, - "ISDN_CMD_ALERT: invalid channel (%d)\n", - (int) cntrl->arg); - return -EINVAL; - } - break; - case ISDN_CMD_REDIR: - gig_dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); - break; - case ISDN_CMD_PROT_IO: - gig_dbg(DEBUG_ANY, "ISDN_CMD_PROT_IO"); - break; - case ISDN_CMD_FAXCMD: - gig_dbg(DEBUG_ANY, "ISDN_CMD_FAXCMD"); - break; - case ISDN_CMD_GETL2: - gig_dbg(DEBUG_ANY, "ISDN_CMD_GETL2"); - break; - case ISDN_CMD_GETL3: - gig_dbg(DEBUG_ANY, "ISDN_CMD_GETL3"); - break; - case ISDN_CMD_GETEAZ: - gig_dbg(DEBUG_ANY, "ISDN_CMD_GETEAZ"); - break; - case ISDN_CMD_SETSIL: - gig_dbg(DEBUG_ANY, "ISDN_CMD_SETSIL"); - break; - case ISDN_CMD_GETSIL: - gig_dbg(DEBUG_ANY, "ISDN_CMD_GETSIL"); - break; + default: - dev_err(cs->dev, "unknown command %d from LL\n", + gig_dbg(DEBUG_CMD, "unknown command %d from LL", cntrl->command); return -EINVAL; } diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index d2260b0055fc..a1bcbc21ff71 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -45,8 +45,6 @@ static int if_lock(struct cardstate *cs, int *arg) cs->waiting = 0; return -ENOMEM; } - - gig_dbg(DEBUG_CMD, "scheduling IF_LOCK"); gigaset_schedule_event(cs); wait_event(cs->waitqueue, !cs->waiting); @@ -81,8 +79,6 @@ static int if_version(struct cardstate *cs, unsigned arg[4]) cs->waiting = 0; return -ENOMEM; } - - gig_dbg(DEBUG_CMD, "scheduling IF_VER"); gigaset_schedule_event(cs); wait_event(cs->waitqueue, !cs->waiting); @@ -274,7 +270,7 @@ static int if_ioctl(struct tty_struct *tty, struct file *file, ? -EFAULT : 0; break; default: - gig_dbg(DEBUG_ANY, "%s: arg not supported - 0x%04x", + gig_dbg(DEBUG_IF, "%s: arg not supported - 0x%04x", __func__, cmd); retval = -ENOIOCTLCMD; } @@ -455,7 +451,7 @@ static void if_throttle(struct tty_struct *tty) else if (!cs->open_count) dev_warn(cs->dev, "%s: device not opened\n", __func__); else - gig_dbg(DEBUG_ANY, "%s: not implemented\n", __func__); + gig_dbg(DEBUG_IF, "%s: not implemented\n", __func__); mutex_unlock(&cs->mutex); } @@ -479,7 +475,7 @@ static void if_unthrottle(struct tty_struct *tty) else if (!cs->open_count) dev_warn(cs->dev, "%s: device not opened\n", __func__); else - gig_dbg(DEBUG_ANY, "%s: not implemented\n", __func__); + gig_dbg(DEBUG_IF, "%s: not implemented\n", __func__); mutex_unlock(&cs->mutex); } @@ -630,7 +626,7 @@ void gigaset_if_receive(struct cardstate *cs, spin_lock_irqsave(&cs->lock, flags); tty = cs->tty; if (tty == NULL) - gig_dbg(DEBUG_ANY, "receive on closed device"); + gig_dbg(DEBUG_IF, "receive on closed device"); else { tty_buffer_request_room(tty, len); tty_insert_flip_string(tty, buffer, len); diff --git a/drivers/isdn/gigaset/proc.c b/drivers/isdn/gigaset/proc.c index 758a00c1d2e2..b69f73a0668f 100644 --- a/drivers/isdn/gigaset/proc.c +++ b/drivers/isdn/gigaset/proc.c @@ -48,8 +48,6 @@ static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, mutex_unlock(&cs->mutex); return -ENOMEM; } - - gig_dbg(DEBUG_CMD, "scheduling PROC_CIDMODE"); gigaset_schedule_event(cs); wait_event(cs->waitqueue, !cs->waiting); diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index 3ab1daeb276b..9430a2bbb523 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c @@ -628,7 +628,7 @@ static int write_modem(struct cardstate *cs) struct usb_cardstate *ucs = cs->hw.usb; unsigned long flags; - gig_dbg(DEBUG_WRITE, "len: %d...", bcs->tx_skb->len); + gig_dbg(DEBUG_OUTPUT, "len: %d...", bcs->tx_skb->len); if (!bcs->tx_skb->len) { dev_kfree_skb_any(bcs->tx_skb); -- cgit v1.2.2 From 003bdb279bb6b212f25ea4e60e0164b6109d3704 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 22 Feb 2010 13:10:22 +0000 Subject: isdn: remove ishexdigit() in regard to isxdigit() Samll cleanup in drivers/isdn/gigaset/capi.c where own implementation of isxdigit() has been changed to kernel native one. Signed-off-by: Andy Shevchenko Acked-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/capi.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index 20ebcee9b0c0..6643d6533ccb 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -170,20 +170,6 @@ static inline void ignore_cstruct_param(struct cardstate *cs, _cstruct param, msgname, paramname); } -/* - * check for legal hex digit - */ -static inline int ishexdigit(char c) -{ - if (c >= '0' && c <= '9') - return 1; - if (c >= 'A' && c <= 'F') - return 1; - if (c >= 'a' && c <= 'f') - return 1; - return 0; -} - /* * convert hex to binary */ @@ -204,7 +190,7 @@ static int encode_ie(char *in, u8 *out, int maxlen) { int l = 0; while (*in) { - if (!ishexdigit(in[0]) || !ishexdigit(in[1]) || l >= maxlen) + if (!isxdigit(in[0]) || !isxdigit(in[1]) || l >= maxlen) return -1; out[++l] = (hex2bin(in[0]) << 4) + hex2bin(in[1]); in += 2; -- cgit v1.2.2 From dec9951b8ad86c591af7b452966bf48b307a4010 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Thu, 11 Mar 2010 12:07:22 +0000 Subject: isdn: misplaced parenthesis in pof_handle_data() The parenthesis was misplaced. Signed-off-by: Roel Kluin Cc: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/isdn/hysdn/hysdn_boot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/hysdn/hysdn_boot.c b/drivers/isdn/hysdn/hysdn_boot.c index be787e16bb79..4f541ef14f9e 100644 --- a/drivers/isdn/hysdn/hysdn_boot.c +++ b/drivers/isdn/hysdn/hysdn_boot.c @@ -143,7 +143,7 @@ pof_handle_data(hysdn_card * card, int datlen) (boot->pof_recid == TAG_CABSDATA) ? "CABSDATA" : "ABSDATA", datlen, boot->pof_recoffset); - if ((boot->last_error = card->writebootseq(card, boot->buf.BootBuf, datlen) < 0)) + if ((boot->last_error = card->writebootseq(card, boot->buf.BootBuf, datlen)) < 0) return (boot->last_error); /* error writing data */ if (boot->pof_recoffset + datlen >= boot->pof_reclen) -- cgit v1.2.2 From 8b4017d8c191822f1c93744e7876c9020e6209aa Mon Sep 17 00:00:00 2001 From: Ian Munsie Date: Thu, 11 Mar 2010 12:07:24 +0000 Subject: i4l: silence compiler warnings for array access in Eicon DIVA ISDN driver When compiling this driver, the compiler throws the following warnings: drivers/isdn/hardware/eicon/message.c:8426: warning: array subscript is above array bounds drivers/isdn/hardware/eicon/message.c:8427: warning: array subscript is above array bounds drivers/isdn/hardware/eicon/message.c:8434: warning: array subscript is above array bounds drivers/isdn/hardware/eicon/message.c:8435: warning: array subscript is above array bounds drivers/isdn/hardware/eicon/message.c:8436: warning: array subscript is above array bounds drivers/isdn/hardware/eicon/message.c:8447: warning: array subscript is above array bounds This arises from the particular semantics the driver is using to write to the nlc array (static byte[256]). The array has a length in byte 0 followed by a T30_INFO struct starting at byte 1. The T30_INFO struct has a number of variable length strings after the station_id entry, which cannot be explicitly defined in the struct and the driver accesses them with an array index to station_id beyond the length of station_id. This patch merely changes the semantics that the driver uses to access the entries after the station_id entry to use the original 256 byte nlc array taking the offset and length of the station_id entry to calculate where to write in the array, thereby silencing the warning. Signed-off-by: Ian Munsie Cc: Armin Schindler Cc: Karsten Keil Cc: Stoyan Gaydarov Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/isdn/hardware/eicon/message.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/hardware/eicon/message.c b/drivers/isdn/hardware/eicon/message.c index ae89fb89da64..4bd469b0c631 100644 --- a/drivers/isdn/hardware/eicon/message.c +++ b/drivers/isdn/hardware/eicon/message.c @@ -8423,17 +8423,17 @@ static word add_b23(PLCI *plci, API_PARSE *bp) pos = 0; else { - ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' '; - ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' '; + nlc[1 + offsetof(T30_INFO, station_id) + 20 + pos++] = ' '; + nlc[1 + offsetof(T30_INFO, station_id) + 20 + pos++] = ' '; len = (byte)b3_config_parms[2].length; if (len > 20) len = 20; if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE) { for (i = 0; i < len; i++) - ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[2].info)[1+i]; - ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' '; - ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' '; + nlc[1 + offsetof(T30_INFO, station_id) + 20 + pos++] = ((byte *)b3_config_parms[2].info)[1+i]; + nlc[1 + offsetof(T30_INFO, station_id) + 20 + pos++] = ' '; + nlc[1 + offsetof(T30_INFO, station_id) + 20 + pos++] = ' '; } } } @@ -8444,9 +8444,8 @@ static word add_b23(PLCI *plci, API_PARSE *bp) ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len); nlc[0] += (byte)(pos + len); for (i = 0; i < len; i++) - ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[3].info)[1+i]; - } - else + nlc[1 + offsetof(T30_INFO, station_id) + 20 + pos++] = ((byte *)b3_config_parms[3].info)[1+i]; + } else ((T30_INFO *)&nlc[1])->head_line_len = 0; plci->nsf_control_bits = 0; -- cgit v1.2.2 From 255f5c327ec3a1d77fe54ef5773ef5eaf7c35a3e Mon Sep 17 00:00:00 2001 From: Ian Munsie Date: Thu, 11 Mar 2010 12:07:25 +0000 Subject: i4l: change magic numbers in Eicon DIVA ISDN driver to symbolic names Replace references to the '20' magic number found throughout the Eicon ISDN driver for the length of the station_id field in the T30_INFO struct with the T30_MAX_STATION_ID_LENGTH symbolic constant. Signed-off-by: Ian Munsie Cc: Armin Schindler Cc: Karsten Keil Cc: Stoyan Gaydarov Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/isdn/hardware/eicon/message.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/hardware/eicon/message.c b/drivers/isdn/hardware/eicon/message.c index 4bd469b0c631..341ef17c22ac 100644 --- a/drivers/isdn/hardware/eicon/message.c +++ b/drivers/isdn/hardware/eicon/message.c @@ -2754,7 +2754,7 @@ static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a, for (i = 0; i < w; i++) ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i]; ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0; - len = offsetof(T30_INFO, station_id) + 20; + len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH; w = fax_parms[5].length; if (w > 20) w = 20; @@ -2892,7 +2892,7 @@ static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a, && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF) && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)) { - len = offsetof(T30_INFO, station_id) + 20; + len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH; if (plci->fax_connect_info_length < len) { ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0; @@ -3802,7 +3802,7 @@ static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a, break; } ncpi = &m_parms[1]; - len = offsetof(T30_INFO, station_id) + 20; + len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH; if (plci->fax_connect_info_length < len) { ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0; @@ -6830,7 +6830,7 @@ static void nl_ind(PLCI *plci) if(((T30_INFO *)plci->NL.RBuffer->P)->station_id_len) { plci->ncpi_buffer[len] = 20; - for (i = 0; i < 20; i++) + for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++) plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i]; } if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)) @@ -6844,7 +6844,7 @@ static void nl_ind(PLCI *plci) if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1]) & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD))) { - i = offsetof(T30_INFO, station_id) + 20 + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len; + i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len; while (i < plci->NL.RBuffer->length) plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++]; } @@ -8400,7 +8400,7 @@ static word add_b23(PLCI *plci, API_PARSE *bp) } } /* copy station id to NLC */ - for(i=0; i<20; i++) + for(i=0; i < T30_MAX_STATION_ID_LENGTH; i++) { if(istation_id[i] = ' '; } } - ((T30_INFO *)&nlc[1])->station_id_len = 20; + ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH; /* copy head line to NLC */ if(b3_config_parms[3].length) { - pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[20]))); + pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH]))); if (pos != 0) { if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE) pos = 0; else { - nlc[1 + offsetof(T30_INFO, station_id) + 20 + pos++] = ' '; - nlc[1 + offsetof(T30_INFO, station_id) + 20 + pos++] = ' '; + nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' '; + nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' '; len = (byte)b3_config_parms[2].length; if (len > 20) len = 20; if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE) { for (i = 0; i < len; i++) - nlc[1 + offsetof(T30_INFO, station_id) + 20 + pos++] = ((byte *)b3_config_parms[2].info)[1+i]; - nlc[1 + offsetof(T30_INFO, station_id) + 20 + pos++] = ' '; - nlc[1 + offsetof(T30_INFO, station_id) + 20 + pos++] = ' '; + nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[2].info)[1+i]; + nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' '; + nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' '; } } } @@ -8444,7 +8444,7 @@ static word add_b23(PLCI *plci, API_PARSE *bp) ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len); nlc[0] += (byte)(pos + len); for (i = 0; i < len; i++) - nlc[1 + offsetof(T30_INFO, station_id) + 20 + pos++] = ((byte *)b3_config_parms[3].info)[1+i]; + nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[3].info)[1+i]; } else ((T30_INFO *)&nlc[1])->head_line_len = 0; @@ -8472,7 +8472,7 @@ static word add_b23(PLCI *plci, API_PARSE *bp) fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING; } len = nlc[0]; - pos = offsetof(T30_INFO, station_id) + 20; + pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH; if (pos < plci->fax_connect_info_length) { for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--) @@ -8524,7 +8524,7 @@ static word add_b23(PLCI *plci, API_PARSE *bp) } PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits); - len = offsetof(T30_INFO, station_id) + 20; + len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH; for (i = 0; i < len; i++) plci->fax_connect_info_buffer[i] = nlc[1+i]; ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0; -- cgit v1.2.2 From bc35b4e347c047fb1c665bb761ddb22482539f7f Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sun, 14 Mar 2010 12:58:05 +0000 Subject: gigaset: avoid registering CAPI driver more than once Registering/unregistering the Gigaset CAPI driver when a device is connected/disconnected causes an Oops when disconnecting two Gigaset devices in a row, because the same capi_driver structure gets unregistered twice. Fix by making driver registration/unregistration a separate operation (empty in the ISDN4Linux case) called when the main module is loaded/unloaded. Impact: bugfix Signed-off-by: Tilman Schmidt Acked-by: Karsten Keil CC: stable@kernel.org Signed-off-by: David S. Miller --- drivers/isdn/gigaset/capi.c | 44 ++++++++++++++++++++++++------------------ drivers/isdn/gigaset/common.c | 6 ++++-- drivers/isdn/gigaset/gigaset.h | 6 ++++-- drivers/isdn/gigaset/i4l.c | 28 +++++++++++++++++++-------- 4 files changed, 53 insertions(+), 31 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index 6643d6533ccb..4a31962ddf71 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -2191,36 +2191,24 @@ static const struct file_operations gigaset_proc_fops = { .release = single_release, }; -static struct capi_driver capi_driver_gigaset = { - .name = "gigaset", - .revision = "1.0", -}; - /** - * gigaset_isdn_register() - register to LL + * gigaset_isdn_regdev() - register device to LL * @cs: device descriptor structure. * @isdnid: device name. * - * Called by main module to register the device with the LL. - * * Return value: 1 for success, 0 for failure */ -int gigaset_isdn_register(struct cardstate *cs, const char *isdnid) +int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid) { struct gigaset_capi_ctr *iif; int rc; - pr_info("Kernel CAPI interface\n"); - iif = kmalloc(sizeof(*iif), GFP_KERNEL); if (!iif) { pr_err("%s: out of memory\n", __func__); return 0; } - /* register driver with CAPI (ToDo: what for?) */ - register_capi_driver(&capi_driver_gigaset); - /* prepare controller structure */ iif->ctr.owner = THIS_MODULE; iif->ctr.driverdata = cs; @@ -2241,7 +2229,6 @@ int gigaset_isdn_register(struct cardstate *cs, const char *isdnid) rc = attach_capi_ctr(&iif->ctr); if (rc) { pr_err("attach_capi_ctr failed (%d)\n", rc); - unregister_capi_driver(&capi_driver_gigaset); kfree(iif); return 0; } @@ -2252,17 +2239,36 @@ int gigaset_isdn_register(struct cardstate *cs, const char *isdnid) } /** - * gigaset_isdn_unregister() - unregister from LL + * gigaset_isdn_unregdev() - unregister device from LL * @cs: device descriptor structure. - * - * Called by main module to unregister the device from the LL. */ -void gigaset_isdn_unregister(struct cardstate *cs) +void gigaset_isdn_unregdev(struct cardstate *cs) { struct gigaset_capi_ctr *iif = cs->iif; detach_capi_ctr(&iif->ctr); kfree(iif); cs->iif = NULL; +} + +static struct capi_driver capi_driver_gigaset = { + .name = "gigaset", + .revision = "1.0", +}; + +/** + * gigaset_isdn_regdrv() - register driver to LL + */ +void gigaset_isdn_regdrv(void) +{ + pr_info("Kernel CAPI interface\n"); + register_capi_driver(&capi_driver_gigaset); +} + +/** + * gigaset_isdn_unregdrv() - unregister driver from LL + */ +void gigaset_isdn_unregdrv(void) +{ unregister_capi_driver(&capi_driver_gigaset); } diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 85de3399a2f2..bdc01cb9f0ab 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -507,7 +507,7 @@ void gigaset_freecs(struct cardstate *cs) case 2: /* error in initcshw */ /* Deregister from LL */ make_invalid(cs, VALID_ID); - gigaset_isdn_unregister(cs); + gigaset_isdn_unregdev(cs); /* fall through */ case 1: /* error when registering to LL */ @@ -769,7 +769,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, cs->cmdbytes = 0; gig_dbg(DEBUG_INIT, "setting up iif"); - if (!gigaset_isdn_register(cs, modulename)) { + if (!gigaset_isdn_regdev(cs, modulename)) { pr_err("error registering ISDN device\n"); goto error; } @@ -1205,11 +1205,13 @@ static int __init gigaset_init_module(void) gigaset_debuglevel = DEBUG_DEFAULT; pr_info(DRIVER_DESC DRIVER_DESC_DEBUG "\n"); + gigaset_isdn_regdrv(); return 0; } static void __exit gigaset_exit_module(void) { + gigaset_isdn_unregdrv(); } module_init(gigaset_init_module); diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 1875ab80b335..cdd144ecdc5f 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -675,8 +675,10 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size); */ /* Called from common.c for setting up/shutting down with the ISDN subsystem */ -int gigaset_isdn_register(struct cardstate *cs, const char *isdnid); -void gigaset_isdn_unregister(struct cardstate *cs); +void gigaset_isdn_regdrv(void); +void gigaset_isdn_unregdrv(void); +int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid); +void gigaset_isdn_unregdev(struct cardstate *cs); /* Called from hardware module to indicate completion of an skb */ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb); diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c index f0acb9dc9e33..c22e5ace8276 100644 --- a/drivers/isdn/gigaset/i4l.c +++ b/drivers/isdn/gigaset/i4l.c @@ -592,15 +592,13 @@ void gigaset_isdn_stop(struct cardstate *cs) } /** - * gigaset_isdn_register() - register to LL + * gigaset_isdn_regdev() - register to LL * @cs: device descriptor structure. * @isdnid: device name. * - * Called by main module to register the device with the LL. - * * Return value: 1 for success, 0 for failure */ -int gigaset_isdn_register(struct cardstate *cs, const char *isdnid) +int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid) { isdn_if *iif; @@ -650,15 +648,29 @@ int gigaset_isdn_register(struct cardstate *cs, const char *isdnid) } /** - * gigaset_isdn_unregister() - unregister from LL + * gigaset_isdn_unregdev() - unregister device from LL * @cs: device descriptor structure. - * - * Called by main module to unregister the device from the LL. */ -void gigaset_isdn_unregister(struct cardstate *cs) +void gigaset_isdn_unregdev(struct cardstate *cs) { gig_dbg(DEBUG_CMD, "sending UNLOAD"); gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD); kfree(cs->iif); cs->iif = NULL; } + +/** + * gigaset_isdn_regdrv() - register driver to LL + */ +void gigaset_isdn_regdrv(void) +{ + /* nothing to do */ +} + +/** + * gigaset_isdn_unregdrv() - unregister driver from LL + */ +void gigaset_isdn_unregdrv(void) +{ + /* nothing to do */ +} -- cgit v1.2.2 From 3a0a3a6b92edf181f849ebd8417122392ba73a96 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sun, 14 Mar 2010 12:58:05 +0000 Subject: gigaset: correct clearing of at_state strings on RING In RING handling, clear the table of received parameter strings in a loop like everywhere else, instead of by enumeration which had already gotten out of sync. Impact: minor bugfix Signed-off-by: Tilman Schmidt Acked-by: Karsten Keil CC: stable@kernel.org Signed-off-by: David S. Miller --- drivers/isdn/gigaset/ev-layer.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index c8f89b78b233..206c380c5235 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c @@ -1258,14 +1258,10 @@ static void do_action(int action, struct cardstate *cs, * note that bcs may be NULL if no B channel is free */ at_state2->ConState = 700; - kfree(at_state2->str_var[STR_NMBR]); - at_state2->str_var[STR_NMBR] = NULL; - kfree(at_state2->str_var[STR_ZCPN]); - at_state2->str_var[STR_ZCPN] = NULL; - kfree(at_state2->str_var[STR_ZBC]); - at_state2->str_var[STR_ZBC] = NULL; - kfree(at_state2->str_var[STR_ZHLC]); - at_state2->str_var[STR_ZHLC] = NULL; + for (i = 0; i < STR_NUM; ++i) { + kfree(at_state2->str_var[i]); + at_state2->str_var[i] = NULL; + } at_state2->int_var[VAR_ZCTP] = -1; spin_lock_irqsave(&cs->lock, flags); -- cgit v1.2.2 From 873a69a358a6b393fd8d9d92e193ec8895cac4d7 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sun, 14 Mar 2010 12:58:05 +0000 Subject: gigaset: prune use of tty_buffer_request_room Calling tty_buffer_request_room() before tty_insert_flip_string() is unnecessary, costs CPU and for big buffers can mess up the multi-page allocation avoidance. Signed-off-by: Tilman Schmidt Acked-by: Karsten Keil CC: Alan Cox , stable@kernel.org Signed-off-by: David S. Miller --- drivers/isdn/gigaset/interface.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index a1bcbc21ff71..f0dc6c9cc283 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -628,7 +628,6 @@ void gigaset_if_receive(struct cardstate *cs, if (tty == NULL) gig_dbg(DEBUG_IF, "receive on closed device"); else { - tty_buffer_request_room(tty, len); tty_insert_flip_string(tty, buffer, len); tty_flip_buffer_push(tty); } -- cgit v1.2.2 From d00561a2f64b381aefb41f4a140ff5dc373b52e7 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Mon, 15 Mar 2010 19:09:28 -0700 Subject: ISDN: Add PCI ID for HFC-2S/4S Beronet Card PCIe A few subdevice IDs seem to have been dropped when hfc_multi was included upstream, just compare the list at http://www.openvox.cn/viewvc/misdn/trunk/hfc_multi.c?revision=75&view=annotate#l175 with the IDs in drivers/isdn/hardware/mISDN/hfcmulti.c Added PCIe 2 Port card and LED settings (same as PCI) Do not use /KKe Signed-off-by: Lars Ellenberg Signed-off-by: Karsten Keil Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/hfcmulti.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/isdn') diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index ad36df9b759c..8affba3e569d 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c @@ -5265,6 +5265,8 @@ static const struct hm_map hfcm_map[] = { /*31*/ {VENDOR_CCD, "XHFC-4S Speech Design", 5, 4, 0, 0, 0, 0, HFC_IO_MODE_EMBSD, XHFC_IRQ}, /*32*/ {VENDOR_JH, "HFC-8S (junghanns)", 8, 8, 1, 0, 0, 0, 0, 0}, +/*33*/ {VENDOR_BN, "HFC-2S Beronet Card PCIe", 4, 2, 1, 3, 0, DIP_4S, 0, 0}, +/*34*/ {VENDOR_BN, "HFC-4S Beronet Card PCIe", 4, 4, 1, 2, 0, DIP_4S, 0, 0}, }; #undef H @@ -5300,6 +5302,10 @@ static struct pci_device_id hfmultipci_ids[] __devinitdata = { PCI_SUBDEVICE_ID_CCD_OV4S, 0, 0, H(28)}, /* OpenVox 4 */ { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD, PCI_SUBDEVICE_ID_CCD_OV2S, 0, 0, H(29)}, /* OpenVox 2 */ + { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD, + 0xb761, 0, 0, H(33)}, /* BN2S PCIe */ + { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD, + 0xb762, 0, 0, H(34)}, /* BN4S PCIe */ /* Cards with HFC-8S Chip */ { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD, -- cgit v1.2.2 From 6ad34145cf809384359fe513481d6e16638a57a3 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Tue, 16 Mar 2010 07:04:01 +0000 Subject: gigaset: correct range checking off by one error Correct a potential array overrun due to an off by one error in the range check on the CAPI CONNECT_REQ CIPValue parameter. Found and reported by Dan Carpenter using smatch. Impact: bugfix Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/capi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index 4a31962ddf71..0220c19351d9 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -1301,7 +1301,7 @@ static void do_connect_req(struct gigaset_capi_ctr *iif, } /* check parameter: CIP Value */ - if (cmsg->CIPValue > ARRAY_SIZE(cip2bchlc) || + if (cmsg->CIPValue >= ARRAY_SIZE(cip2bchlc) || (cmsg->CIPValue > 0 && cip2bchlc[cmsg->CIPValue].bc == NULL)) { dev_notice(cs->dev, "%s: unknown CIP value %d\n", "CONNECT_REQ", cmsg->CIPValue); -- cgit v1.2.2 From 22001a13d09d82772e831dcdac0553994a4bac5d Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Wed, 17 Mar 2010 14:22:07 -0700 Subject: gigaset: fix build failure Update the dummy LL interface to the LL interface change introduced by commit daab433c03c15fd642c71c94eb51bdd3f32602c8. This fixes the build failure occurring after that commit when enabling ISDN_DRV_GIGASET but neither ISDN_I4L nor ISDN_CAPI. Impact: bugfix Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/dummyll.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/dummyll.c b/drivers/isdn/gigaset/dummyll.c index 5b27c996af6d..bd0b1eaa7572 100644 --- a/drivers/isdn/gigaset/dummyll.c +++ b/drivers/isdn/gigaset/dummyll.c @@ -57,12 +57,20 @@ void gigaset_isdn_stop(struct cardstate *cs) { } -int gigaset_isdn_register(struct cardstate *cs, const char *isdnid) +int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid) { - pr_info("no ISDN subsystem interface\n"); return 1; } -void gigaset_isdn_unregister(struct cardstate *cs) +void gigaset_isdn_unregdev(struct cardstate *cs) +{ +} + +void gigaset_isdn_regdrv(void) +{ + pr_info("no ISDN subsystem interface\n"); +} + +void gigaset_isdn_unregdrv(void) { } -- cgit v1.2.2 From 93b39a0dba6a15c35a582b9e8b171b8a6ec971aa Mon Sep 17 00:00:00 2001 From: Henne Date: Thu, 25 Mar 2010 12:05:29 +0000 Subject: isdn: Cleanup Sections in PCMCIA driver sedlbauer Compiling this driver gave a section mismatch, so I reviewed the init/exit paths of the driver and made the correct changes. WARNING: drivers/isdn/hisax/built-in.o(.text+0x558d6): Section mismatch in reference from the function sedlbauer_config() to the function .devinit.text:hisax_init_pcmcia() The function sedlbauer_config() references the function __devinit hisax_init_pcmcia(). This is often because sedlbauer_config lacks a __devinit annotation or the annotation of hisax_init_pcmcia is wrong. Signed-off-by: Henrik Kretzschmar Acked-by: Karsten Keil Signed-off-by: David S. Miller --- drivers/isdn/hisax/sedlbauer_cs.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index 7836ec3c7f86..71b3ddef03bb 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -76,7 +76,7 @@ module_param(protocol, int, 0); event handler. */ -static int sedlbauer_config(struct pcmcia_device *link); +static int sedlbauer_config(struct pcmcia_device *link) __devinit ; static void sedlbauer_release(struct pcmcia_device *link); /* @@ -85,7 +85,7 @@ static void sedlbauer_release(struct pcmcia_device *link); needed to manage one actual PCMCIA card. */ -static void sedlbauer_detach(struct pcmcia_device *p_dev); +static void sedlbauer_detach(struct pcmcia_device *p_dev) __devexit; /* You'll also need to prototype all the functions that will actually @@ -129,7 +129,7 @@ typedef struct local_info_t { ======================================================================*/ -static int sedlbauer_probe(struct pcmcia_device *link) +static int __devinit sedlbauer_probe(struct pcmcia_device *link) { local_info_t *local; @@ -177,7 +177,7 @@ static int sedlbauer_probe(struct pcmcia_device *link) ======================================================================*/ -static void sedlbauer_detach(struct pcmcia_device *link) +static void __devexit sedlbauer_detach(struct pcmcia_device *link) { dev_dbg(&link->dev, "sedlbauer_detach(0x%p)\n", link); @@ -283,7 +283,7 @@ static int sedlbauer_config_check(struct pcmcia_device *p_dev, -static int sedlbauer_config(struct pcmcia_device *link) +static int __devinit sedlbauer_config(struct pcmcia_device *link) { local_info_t *dev = link->priv; win_req_t *req; @@ -441,7 +441,7 @@ static struct pcmcia_driver sedlbauer_driver = { .name = "sedlbauer_cs", }, .probe = sedlbauer_probe, - .remove = sedlbauer_detach, + .remove = __devexit_p(sedlbauer_detach), .id_table = sedlbauer_ids, .suspend = sedlbauer_suspend, .resume = sedlbauer_resume, -- cgit v1.2.2 From 158e33d1c6d0c6bacf577bcb47591aa4293dfcb1 Mon Sep 17 00:00:00 2001 From: Henne Date: Thu, 25 Mar 2010 12:05:30 +0000 Subject: isdn: Cleanup Sections in PCMCIA driver teles Compiling this driver gave a section mismatch, so I reviewed the init/exit paths of the driver and made the correct changes. WARNING: drivers/isdn/hisax/built-in.o(.text+0x56bfb): Section mismatch in reference from the function teles_cs_config() to the function .devinit.text:hisax_init_pcmcia() The function teles_cs_config() references the function __devinit hisax_init_pcmcia(). This is often because teles_cs_config lacks a __devinit annotation or the annotation of hisax_init_pcmcia is wrong. Signed-off-by: Henrik Kretzschmar Acked-by: Karsten Keil Signed-off-by: David S. Miller --- drivers/isdn/hisax/teles_cs.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index b0c5976cbdb3..d010a0da8e19 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c @@ -57,7 +57,7 @@ module_param(protocol, int, 0); handler. */ -static int teles_cs_config(struct pcmcia_device *link); +static int teles_cs_config(struct pcmcia_device *link) __devinit ; static void teles_cs_release(struct pcmcia_device *link); /* @@ -66,7 +66,7 @@ static void teles_cs_release(struct pcmcia_device *link); needed to manage one actual PCMCIA card. */ -static void teles_detach(struct pcmcia_device *p_dev); +static void teles_detach(struct pcmcia_device *p_dev) __devexit ; /* A linked list of "instances" of the teles_cs device. Each actual @@ -112,7 +112,7 @@ typedef struct local_info_t { ======================================================================*/ -static int teles_probe(struct pcmcia_device *link) +static int __devinit teles_probe(struct pcmcia_device *link) { local_info_t *local; @@ -156,7 +156,7 @@ static int teles_probe(struct pcmcia_device *link) ======================================================================*/ -static void teles_detach(struct pcmcia_device *link) +static void __devexit teles_detach(struct pcmcia_device *link) { local_info_t *info = link->priv; @@ -200,7 +200,7 @@ static int teles_cs_configcheck(struct pcmcia_device *p_dev, return -ENODEV; } -static int teles_cs_config(struct pcmcia_device *link) +static int __devinit teles_cs_config(struct pcmcia_device *link) { local_info_t *dev; int i; @@ -319,7 +319,7 @@ static struct pcmcia_driver teles_cs_driver = { .name = "teles_cs", }, .probe = teles_probe, - .remove = teles_detach, + .remove = __devexit_p(teles_detach), .id_table = teles_ids, .suspend = teles_suspend, .resume = teles_resume, -- cgit v1.2.2 From a465870a808bccba63bf6da30a0b56a2a7abfa5c Mon Sep 17 00:00:00 2001 From: Henne Date: Thu, 25 Mar 2010 12:05:31 +0000 Subject: isdn: Cleanup Sections in PCMCIA driver avma1 Compiling this driver gave a section mismatch, so I reviewed the init/exit paths of the driver and made the correct changes. WARNING: drivers/isdn/hisax/built-in.o(.text+0x56512): Section mismatch in reference from the function avma1cs_config() to the function .devinit.text:hisax_init_pcmcia() The function avma1cs_config() references the function __devinit hisax_init_pcmcia(). This is often because avma1cs_config lacks a __devinit annotation or the annotation of hisax_init_pcmcia is wrong. Signed-off-by: Henrik Kretzschmar Acked-by: Karsten Keil Signed-off-by: David S. Miller --- drivers/isdn/hisax/avma1_cs.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index e5deb15cf40c..8d1d63a02b34 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c @@ -50,7 +50,7 @@ module_param(isdnprot, int, 0); handler. */ -static int avma1cs_config(struct pcmcia_device *link); +static int avma1cs_config(struct pcmcia_device *link) __devinit ; static void avma1cs_release(struct pcmcia_device *link); /* @@ -59,7 +59,7 @@ static void avma1cs_release(struct pcmcia_device *link); needed to manage one actual PCMCIA card. */ -static void avma1cs_detach(struct pcmcia_device *p_dev); +static void avma1cs_detach(struct pcmcia_device *p_dev) __devexit ; /* @@ -99,7 +99,7 @@ typedef struct local_info_t { ======================================================================*/ -static int avma1cs_probe(struct pcmcia_device *p_dev) +static int __devinit avma1cs_probe(struct pcmcia_device *p_dev) { local_info_t *local; @@ -140,7 +140,7 @@ static int avma1cs_probe(struct pcmcia_device *p_dev) ======================================================================*/ -static void avma1cs_detach(struct pcmcia_device *link) +static void __devexit avma1cs_detach(struct pcmcia_device *link) { dev_dbg(&link->dev, "avma1cs_detach(0x%p)\n", link); avma1cs_release(link); @@ -174,7 +174,7 @@ static int avma1cs_configcheck(struct pcmcia_device *p_dev, } -static int avma1cs_config(struct pcmcia_device *link) +static int __devinit avma1cs_config(struct pcmcia_device *link) { local_info_t *dev; int i; @@ -282,7 +282,7 @@ static struct pcmcia_driver avma1cs_driver = { .name = "avma1_cs", }, .probe = avma1cs_probe, - .remove = avma1cs_detach, + .remove = __devexit_p(avma1cs_detach), .id_table = avma1cs_ids, }; -- cgit v1.2.2 From f61bb62e3ed7634fe5b7dfd8c9a52e6b799f4023 Mon Sep 17 00:00:00 2001 From: Henne Date: Thu, 25 Mar 2010 12:05:32 +0000 Subject: isdn: Cleanup Sections in PCMCIA driver elsa Compiling this driver gave a section mismatch, so I reviewed the init/exit paths of the driver and made the correct changes. WARNING: drivers/isdn/hisax/built-in.o(.text+0x55e37): Section mismatch in reference from the function elsa_cs_config() to the function .devinit.text:hisax_init_pcmcia() The function elsa_cs_config() references the function __devinit hisax_init_pcmcia(). This is often because elsa_cs_config lacks a __devinit annotation or the annotation of hisax_init_pcmcia is wrong. Signed-off-by: Henrik Kretzschmar Acked-by: Karsten Keil Signed-off-by: David S. Miller --- drivers/isdn/hisax/elsa_cs.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index c9a30b1c9237..c9f2279e21f5 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -76,7 +76,7 @@ module_param(protocol, int, 0); handler. */ -static int elsa_cs_config(struct pcmcia_device *link); +static int elsa_cs_config(struct pcmcia_device *link) __devinit ; static void elsa_cs_release(struct pcmcia_device *link); /* @@ -85,7 +85,7 @@ static void elsa_cs_release(struct pcmcia_device *link); needed to manage one actual PCMCIA card. */ -static void elsa_cs_detach(struct pcmcia_device *p_dev); +static void elsa_cs_detach(struct pcmcia_device *p_dev) __devexit; /* A driver needs to provide a dev_node_t structure for each device @@ -121,7 +121,7 @@ typedef struct local_info_t { ======================================================================*/ -static int elsa_cs_probe(struct pcmcia_device *link) +static int __devinit elsa_cs_probe(struct pcmcia_device *link) { local_info_t *local; @@ -166,7 +166,7 @@ static int elsa_cs_probe(struct pcmcia_device *link) ======================================================================*/ -static void elsa_cs_detach(struct pcmcia_device *link) +static void __devexit elsa_cs_detach(struct pcmcia_device *link) { local_info_t *info = link->priv; @@ -210,7 +210,7 @@ static int elsa_cs_configcheck(struct pcmcia_device *p_dev, return -ENODEV; } -static int elsa_cs_config(struct pcmcia_device *link) +static int __devinit elsa_cs_config(struct pcmcia_device *link) { local_info_t *dev; int i; @@ -327,7 +327,7 @@ static struct pcmcia_driver elsa_cs_driver = { .name = "elsa_cs", }, .probe = elsa_cs_probe, - .remove = elsa_cs_detach, + .remove = __devexit_p(elsa_cs_detach), .id_table = elsa_ids, .suspend = elsa_suspend, .resume = elsa_resume, -- cgit v1.2.2 From 5a0e3ad6af8660be21ca98a971cd00f331318c05 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 24 Mar 2010 17:04:11 +0900 Subject: include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h percpu.h is included by sched.h and module.h and thus ends up being included when building most .c files. percpu.h includes slab.h which in turn includes gfp.h making everything defined by the two files universally available and complicating inclusion dependencies. percpu.h -> slab.h dependency is about to be removed. Prepare for this change by updating users of gfp and slab facilities include those headers directly instead of assuming availability. As this conversion needs to touch large number of source files, the following script is used as the basis of conversion. http://userweb.kernel.org/~tj/misc/slabh-sweep.py The script does the followings. * Scan files for gfp and slab usages and update includes such that only the necessary includes are there. ie. if only gfp is used, gfp.h, if slab is used, slab.h. * When the script inserts a new include, it looks at the include blocks and try to put the new include such that its order conforms to its surrounding. It's put in the include block which contains core kernel includes, in the same order that the rest are ordered - alphabetical, Christmas tree, rev-Xmas-tree or at the end if there doesn't seem to be any matching order. * If the script can't find a place to put a new include (mostly because the file doesn't have fitting include block), it prints out an error message indicating which .h file needs to be added to the file. The conversion was done in the following steps. 1. The initial automatic conversion of all .c files updated slightly over 4000 files, deleting around 700 includes and adding ~480 gfp.h and ~3000 slab.h inclusions. The script emitted errors for ~400 files. 2. Each error was manually checked. Some didn't need the inclusion, some needed manual addition while adding it to implementation .h or embedding .c file was more appropriate for others. This step added inclusions to around 150 files. 3. The script was run again and the output was compared to the edits from #2 to make sure no file was left behind. 4. Several build tests were done and a couple of problems were fixed. e.g. lib/decompress_*.c used malloc/free() wrappers around slab APIs requiring slab.h to be added manually. 5. The script was run on all .h files but without automatically editing them as sprinkling gfp.h and slab.h inclusions around .h files could easily lead to inclusion dependency hell. Most gfp.h inclusion directives were ignored as stuff from gfp.h was usually wildly available and often used in preprocessor macros. Each slab.h inclusion directive was examined and added manually as necessary. 6. percpu.h was updated not to include slab.h. 7. Build test were done on the following configurations and failures were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my distributed build env didn't work with gcov compiles) and a few more options had to be turned off depending on archs to make things build (like ipr on powerpc/64 which failed due to missing writeq). * x86 and x86_64 UP and SMP allmodconfig and a custom test config. * powerpc and powerpc64 SMP allmodconfig * sparc and sparc64 SMP allmodconfig * ia64 SMP allmodconfig * s390 SMP allmodconfig * alpha SMP allmodconfig * um on x86_64 SMP allmodconfig 8. percpu.h modifications were reverted so that it could be applied as a separate patch and serve as bisection point. Given the fact that I had only a couple of failures from tests on step 6, I'm fairly confident about the coverage of this conversion patch. If there is a breakage, it's likely to be something in one of the arch headers which should be easily discoverable easily on most builds of the specific arch. Signed-off-by: Tejun Heo Guess-its-ok-by: Christoph Lameter Cc: Ingo Molnar Cc: Lee Schermerhorn --- drivers/isdn/act2000/module.c | 1 + drivers/isdn/capi/capifs.c | 1 + drivers/isdn/capi/capilib.c | 1 + drivers/isdn/capi/capiutil.c | 1 + drivers/isdn/capi/kcapi.c | 1 + drivers/isdn/divert/divert_procfs.c | 1 + drivers/isdn/divert/isdn_divert.c | 1 + drivers/isdn/gigaset/capi.c | 1 + drivers/isdn/gigaset/common.c | 1 + drivers/isdn/gigaset/gigaset.h | 1 + drivers/isdn/gigaset/i4l.c | 1 + drivers/isdn/gigaset/ser-gigaset.c | 1 + drivers/isdn/hardware/avm/b1.c | 1 + drivers/isdn/hardware/avm/b1dma.c | 1 + drivers/isdn/hardware/avm/c4.c | 1 + drivers/isdn/hardware/avm/t1isa.c | 1 + drivers/isdn/hardware/eicon/capimain.c | 1 + drivers/isdn/hardware/mISDN/avmfritz.c | 1 + drivers/isdn/hardware/mISDN/hfcmulti.c | 1 + drivers/isdn/hardware/mISDN/hfcpci.c | 1 + drivers/isdn/hardware/mISDN/hfcsusb.c | 1 + drivers/isdn/hardware/mISDN/mISDNinfineon.c | 1 + drivers/isdn/hardware/mISDN/mISDNipac.c | 1 + drivers/isdn/hardware/mISDN/mISDNisar.c | 1 + drivers/isdn/hardware/mISDN/netjet.c | 1 + drivers/isdn/hardware/mISDN/speedfax.c | 1 + drivers/isdn/hardware/mISDN/w6692.c | 1 + drivers/isdn/hisax/amd7930_fn.c | 1 + drivers/isdn/hisax/avm_pci.c | 1 + drivers/isdn/hisax/callc.c | 1 + drivers/isdn/hisax/config.c | 1 + drivers/isdn/hisax/elsa.c | 1 + drivers/isdn/hisax/elsa_ser.c | 1 + drivers/isdn/hisax/fsm.c | 1 + drivers/isdn/hisax/hfc4s8s_l1.c | 1 + drivers/isdn/hisax/hfc_2bds0.c | 1 + drivers/isdn/hisax/hfc_2bs0.c | 1 + drivers/isdn/hisax/hfc_sx.c | 1 + drivers/isdn/hisax/hfc_usb.c | 1 + drivers/isdn/hisax/hisax_isac.c | 1 + drivers/isdn/hisax/hscx.c | 1 + drivers/isdn/hisax/icc.c | 1 + drivers/isdn/hisax/ipacx.c | 1 + drivers/isdn/hisax/isac.c | 1 + drivers/isdn/hisax/isar.c | 1 + drivers/isdn/hisax/isdnl1.c | 1 + drivers/isdn/hisax/isdnl2.c | 1 + drivers/isdn/hisax/isdnl3.c | 1 + drivers/isdn/hisax/jade.c | 1 + drivers/isdn/hisax/l3dss1.c | 1 + drivers/isdn/hisax/l3ni1.c | 1 + drivers/isdn/hisax/netjet.c | 1 + drivers/isdn/hisax/st5481_b.c | 2 +- drivers/isdn/hisax/st5481_d.c | 2 +- drivers/isdn/hisax/tei.c | 1 + drivers/isdn/hisax/w6692.c | 1 + drivers/isdn/hysdn/hycapi.c | 1 + drivers/isdn/hysdn/hysdn_procconf.c | 1 + drivers/isdn/hysdn/hysdn_proclog.c | 1 + drivers/isdn/i4l/isdn_audio.c | 1 + drivers/isdn/i4l/isdn_common.c | 1 + drivers/isdn/i4l/isdn_net.c | 1 + drivers/isdn/i4l/isdn_ppp.c | 1 + drivers/isdn/i4l/isdn_tty.c | 1 + drivers/isdn/i4l/isdn_x25iface.c | 1 + drivers/isdn/icn/icn.c | 1 + drivers/isdn/isdnloop/isdnloop.c | 1 + drivers/isdn/mISDN/clock.c | 1 + drivers/isdn/mISDN/core.c | 1 + drivers/isdn/mISDN/dsp_cmx.c | 1 + drivers/isdn/mISDN/dsp_core.c | 1 + drivers/isdn/mISDN/dsp_pipeline.c | 1 + drivers/isdn/mISDN/dsp_tones.c | 1 + drivers/isdn/mISDN/hwchannel.c | 1 + drivers/isdn/mISDN/l1oip_core.c | 1 + drivers/isdn/mISDN/layer1.c | 1 + drivers/isdn/mISDN/layer2.c | 1 + drivers/isdn/mISDN/socket.c | 1 + drivers/isdn/mISDN/stack.c | 1 + drivers/isdn/mISDN/tei.c | 1 + drivers/isdn/mISDN/timerdev.c | 1 + drivers/isdn/pcbit/callbacks.c | 1 - drivers/isdn/pcbit/edss1.c | 1 - drivers/isdn/sc/init.c | 1 + 84 files changed, 82 insertions(+), 4 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/act2000/module.c b/drivers/isdn/act2000/module.c index f774e12bb64d..05ed72c4cf59 100644 --- a/drivers/isdn/act2000/module.c +++ b/drivers/isdn/act2000/module.c @@ -16,6 +16,7 @@ #include "act2000_isa.h" #include "capi.h" #include +#include #include static unsigned short act2000_isa_ports[] = diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c index 8596bd1a4d26..2b83850997c3 100644 --- a/drivers/isdn/capi/capifs.c +++ b/drivers/isdn/capi/capifs.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include diff --git a/drivers/isdn/capi/capilib.c b/drivers/isdn/capi/capilib.c index fcaa1241ee77..0b041df2108c 100644 --- a/drivers/isdn/capi/capilib.c +++ b/drivers/isdn/capi/capilib.c @@ -1,4 +1,5 @@ +#include #include #include #include diff --git a/drivers/isdn/capi/capiutil.c b/drivers/isdn/capi/capiutil.c index 26626eead828..03c469e4451f 100644 --- a/drivers/isdn/capi/capiutil.c +++ b/drivers/isdn/capi/capiutil.c @@ -18,6 +18,7 @@ #include #include #include +#include /* from CAPI2.0 DDK AVM Berlin GmbH */ diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index ce9b05b9e93a..bd00dceacaf0 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c index 3697c409bec6..9f49d9065791 100644 --- a/drivers/isdn/divert/divert_procfs.c +++ b/drivers/isdn/divert/divert_procfs.c @@ -11,6 +11,7 @@ #include #include +#include #ifdef CONFIG_PROC_FS #include #else diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c index 77e9fdda0597..70cf6bac7a5a 100644 --- a/drivers/isdn/divert/isdn_divert.c +++ b/drivers/isdn/divert/isdn_divert.c @@ -10,6 +10,7 @@ */ #include +#include #include #include diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index 0220c19351d9..eb7e27105a82 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -12,6 +12,7 @@ */ #include "gigaset.h" +#include #include #include #include diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index bdc01cb9f0ab..0b39b387c125 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -17,6 +17,7 @@ #include #include #include +#include /* Version Information */ #define DRIVER_AUTHOR "Hansjoerg Lipp , Tilman Schmidt , Stefan Eilers" diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index cdd144ecdc5f..9ef5b0463fd5 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c index c22e5ace8276..c99fb9790a13 100644 --- a/drivers/isdn/gigaset/i4l.c +++ b/drivers/isdn/gigaset/i4l.c @@ -15,6 +15,7 @@ #include "gigaset.h" #include +#include #define HW_HDR_LEN 2 /* Header size used to store ack info */ diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index 168d585d64d8..8b0afd203a07 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c @@ -17,6 +17,7 @@ #include #include #include +#include /* Version Information */ #define DRIVER_AUTHOR "Tilman Schmidt" diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c index c38fa0f4c729..2a57da590d79 100644 --- a/drivers/isdn/hardware/avm/b1.c +++ b/drivers/isdn/hardware/avm/b1.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c index 124550d0dbf3..9c8d7aa053c5 100644 --- a/drivers/isdn/hardware/avm/b1dma.c +++ b/drivers/isdn/hardware/avm/b1dma.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c index de6e6b311819..7715d3242ec8 100644 --- a/drivers/isdn/hardware/avm/c4.c +++ b/drivers/isdn/hardware/avm/c4.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/isdn/hardware/avm/t1isa.c b/drivers/isdn/hardware/avm/t1isa.c index baeeb3c2a3ee..08216b14be13 100644 --- a/drivers/isdn/hardware/avm/t1isa.c +++ b/drivers/isdn/hardware/avm/t1isa.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/isdn/hardware/eicon/capimain.c b/drivers/isdn/hardware/eicon/capimain.c index 0f073cd73763..97a20964cfc7 100644 --- a/drivers/isdn/hardware/eicon/capimain.c +++ b/drivers/isdn/hardware/eicon/capimain.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c index 81ac541d40d9..d4215369bb59 100644 --- a/drivers/isdn/hardware/mISDN/avmfritz.c +++ b/drivers/isdn/hardware/mISDN/avmfritz.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "ipac.h" diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index 8affba3e569d..75e71b5d9215 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c @@ -153,6 +153,7 @@ #define HFC_MULTI_VERSION "2.03" #include +#include #include #include #include diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c index 70e6b0e01121..5940a2c12074 100644 --- a/drivers/isdn/hardware/mISDN/hfcpci.c +++ b/drivers/isdn/hardware/mISDN/hfcpci.c @@ -48,6 +48,7 @@ #include #include #include +#include #include "hfc_pci.h" diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c index a64bb6c67ba7..b3b7e2879bac 100644 --- a/drivers/isdn/hardware/mISDN/hfcsusb.c +++ b/drivers/isdn/hardware/mISDN/hfcsusb.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "hfcsusb.h" static const char *hfcsusb_rev = "Revision: 0.3.3 (socket), 2008-11-05"; diff --git a/drivers/isdn/hardware/mISDN/mISDNinfineon.c b/drivers/isdn/hardware/mISDN/mISDNinfineon.c index 36c6c616a655..f5b3d2b26a08 100644 --- a/drivers/isdn/hardware/mISDN/mISDNinfineon.c +++ b/drivers/isdn/hardware/mISDN/mISDNinfineon.c @@ -42,6 +42,7 @@ #include #include #include +#include #include "ipac.h" #define INFINEON_REV "1.0" diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c index 613ba0435372..64ecc6f5ffaf 100644 --- a/drivers/isdn/hardware/mISDN/mISDNipac.c +++ b/drivers/isdn/hardware/mISDN/mISDNipac.c @@ -20,6 +20,7 @@ * */ +#include #include #include #include "ipac.h" diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c index f0bc6fa95809..38eb31439a73 100644 --- a/drivers/isdn/hardware/mISDN/mISDNisar.c +++ b/drivers/isdn/hardware/mISDN/mISDNisar.c @@ -25,6 +25,7 @@ */ /* #define DEBUG */ +#include #include #include #include diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c index 6c1b164937a9..0a3553df065f 100644 --- a/drivers/isdn/hardware/mISDN/netjet.c +++ b/drivers/isdn/hardware/mISDN/netjet.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "ipac.h" #include "iohelper.h" #include "netjet.h" diff --git a/drivers/isdn/hardware/mISDN/speedfax.c b/drivers/isdn/hardware/mISDN/speedfax.c index 7726afdbb40b..d097a4e40e2b 100644 --- a/drivers/isdn/hardware/mISDN/speedfax.c +++ b/drivers/isdn/hardware/mISDN/speedfax.c @@ -23,6 +23,7 @@ */ #include +#include #include #include #include diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c index 2952a58c7a61..31f9d71fb22f 100644 --- a/drivers/isdn/hardware/mISDN/w6692.c +++ b/drivers/isdn/hardware/mISDN/w6692.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "w6692.h" #define W6692_REV "2.0" diff --git a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c index d6fdf1f66754..5d7278397878 100644 --- a/drivers/isdn/hisax/amd7930_fn.c +++ b/drivers/isdn/hisax/amd7930_fn.c @@ -59,6 +59,7 @@ #include "amd7930_fn.h" #include #include +#include static void Amd7930_new_ph(struct IsdnCardState *cs); diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c index 14295a155e71..fcf4ed1cb4b9 100644 --- a/drivers/isdn/hisax/avm_pci.c +++ b/drivers/isdn/hisax/avm_pci.c @@ -17,6 +17,7 @@ #include "isac.h" #include "isdnl1.h" #include +#include #include #include diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c index 475b1a020003..f58ded8f403f 100644 --- a/drivers/isdn/hisax/callc.c +++ b/drivers/isdn/hisax/callc.c @@ -17,6 +17,7 @@ */ #include +#include #include #include "hisax.h" #include diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index 4fab18d4d02f..544cf4b1cce3 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -23,6 +23,7 @@ #include #include #include +#include #define HISAX_STATUS_BUFSIZE 4096 /* diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c index 23c41fcd864e..5d9d338814aa 100644 --- a/drivers/isdn/hisax/elsa.c +++ b/drivers/isdn/hisax/elsa.c @@ -19,6 +19,7 @@ */ #include +#include #include "hisax.h" #include "arcofi.h" #include "isac.h" diff --git a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c index 1657bba7879e..cbda3790a10d 100644 --- a/drivers/isdn/hisax/elsa_ser.c +++ b/drivers/isdn/hisax/elsa_ser.c @@ -9,6 +9,7 @@ #include #include +#include #define MAX_MODEM_BUF 256 #define WAKEUP_CHARS (MAX_MODEM_BUF/2) diff --git a/drivers/isdn/hisax/fsm.c b/drivers/isdn/hisax/fsm.c index 34fade96a581..732ea633758c 100644 --- a/drivers/isdn/hisax/fsm.c +++ b/drivers/isdn/hisax/fsm.c @@ -15,6 +15,7 @@ */ #include +#include #include #include "hisax.h" diff --git a/drivers/isdn/hisax/hfc4s8s_l1.c b/drivers/isdn/hisax/hfc4s8s_l1.c index ab98e135bcbb..051b44e2556c 100644 --- a/drivers/isdn/hisax/hfc4s8s_l1.c +++ b/drivers/isdn/hisax/hfc4s8s_l1.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c index 8d22f50760eb..7250f56a5246 100644 --- a/drivers/isdn/hisax/hfc_2bds0.c +++ b/drivers/isdn/hisax/hfc_2bds0.c @@ -12,6 +12,7 @@ #include #include +#include #include "hisax.h" #include "hfc_2bds0.h" #include "isdnl1.h" diff --git a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c index d0520ad30677..b1f6481e1193 100644 --- a/drivers/isdn/hisax/hfc_2bs0.c +++ b/drivers/isdn/hisax/hfc_2bs0.c @@ -16,6 +16,7 @@ #include "isac.h" #include "isdnl1.h" #include +#include static inline int WaitForBusy(struct IsdnCardState *cs) diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c index 419f87cad8cb..be5faf4aa868 100644 --- a/drivers/isdn/hisax/hfc_sx.c +++ b/drivers/isdn/hisax/hfc_sx.c @@ -17,6 +17,7 @@ #include "isdnl1.h" #include #include +#include static const char *hfcsx_revision = "$Revision: 1.12.2.5 $"; diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c index aaaeaafd86f4..ed9527aa5f2c 100644 --- a/drivers/isdn/hisax/hfc_usb.c +++ b/drivers/isdn/hisax/hfc_usb.c @@ -39,6 +39,7 @@ #include #include #include +#include #include "hisax.h" #include "hisax_if.h" #include "hfc_usb.h" diff --git a/drivers/isdn/hisax/hisax_isac.c b/drivers/isdn/hisax/hisax_isac.c index d0fefcf999cb..a8447fa2f470 100644 --- a/drivers/isdn/hisax/hisax_isac.c +++ b/drivers/isdn/hisax/hisax_isac.c @@ -21,6 +21,7 @@ */ #include +#include #include #include #include "hisax_isac.h" diff --git a/drivers/isdn/hisax/hscx.c b/drivers/isdn/hisax/hscx.c index c8f9951f7914..904b9100df95 100644 --- a/drivers/isdn/hisax/hscx.c +++ b/drivers/isdn/hisax/hscx.c @@ -16,6 +16,7 @@ #include "isac.h" #include "isdnl1.h" #include +#include static char *HSCXVer[] = {"A1", "?1", "A2", "?3", "A3", "V2.1", "?6", "?7", diff --git a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c index c80cbb8a2ef9..63057268cc3d 100644 --- a/drivers/isdn/hisax/icc.c +++ b/drivers/isdn/hisax/icc.c @@ -20,6 +20,7 @@ // #include "arcofi.h" #include "isdnl1.h" #include +#include #define DBUSY_TIMER_VALUE 80 #define ARCOFI_USE 0 diff --git a/drivers/isdn/hisax/ipacx.c b/drivers/isdn/hisax/ipacx.c index 00afd5538909..751b25f2ff58 100644 --- a/drivers/isdn/hisax/ipacx.c +++ b/drivers/isdn/hisax/ipacx.c @@ -10,6 +10,7 @@ * */ #include +#include #include #include "hisax_if.h" #include "hisax.h" diff --git a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c index a19354d94343..2b66728136d5 100644 --- a/drivers/isdn/hisax/isac.c +++ b/drivers/isdn/hisax/isac.c @@ -18,6 +18,7 @@ #include "arcofi.h" #include "isdnl1.h" #include +#include #include #define DBUSY_TIMER_VALUE 80 diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c index 6bde16c00fb5..40b914bded8c 100644 --- a/drivers/isdn/hisax/isar.c +++ b/drivers/isdn/hisax/isar.c @@ -13,6 +13,7 @@ #include "isar.h" #include "isdnl1.h" #include +#include #define DBG_LOADFIRM 0 #define DUMP_MBOXFRAME 2 diff --git a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c index 9ce6abe05b1a..d5eeacf565d6 100644 --- a/drivers/isdn/hisax/isdnl1.c +++ b/drivers/isdn/hisax/isdnl1.c @@ -19,6 +19,7 @@ */ #include +#include #include "hisax.h" #include "isdnl1.h" diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c index 7b9496a63b5f..0858791978d8 100644 --- a/drivers/isdn/hisax/isdnl2.c +++ b/drivers/isdn/hisax/isdnl2.c @@ -16,6 +16,7 @@ */ #include +#include #include "hisax.h" #include "isdnl2.h" diff --git a/drivers/isdn/hisax/isdnl3.c b/drivers/isdn/hisax/isdnl3.c index 06766022d3ae..fd0b643ab740 100644 --- a/drivers/isdn/hisax/isdnl3.c +++ b/drivers/isdn/hisax/isdnl3.c @@ -16,6 +16,7 @@ */ #include +#include #include "hisax.h" #include "isdnl3.h" diff --git a/drivers/isdn/hisax/jade.c b/drivers/isdn/hisax/jade.c index 70840a710acf..ea8f840871d0 100644 --- a/drivers/isdn/hisax/jade.c +++ b/drivers/isdn/hisax/jade.c @@ -17,6 +17,7 @@ #include "jade.h" #include "isdnl1.h" #include +#include int diff --git a/drivers/isdn/hisax/l3dss1.c b/drivers/isdn/hisax/l3dss1.c index a12fa4d34903..cc6ee2d39880 100644 --- a/drivers/isdn/hisax/l3dss1.c +++ b/drivers/isdn/hisax/l3dss1.c @@ -23,6 +23,7 @@ #include "isdnl3.h" #include "l3dss1.h" #include +#include extern char *HiSax_getrev(const char *revision); static const char *dss1_revision = "$Revision: 2.32.2.3 $"; diff --git a/drivers/isdn/hisax/l3ni1.c b/drivers/isdn/hisax/l3ni1.c index 4622d43c7e10..f9584491fe8e 100644 --- a/drivers/isdn/hisax/l3ni1.c +++ b/drivers/isdn/hisax/l3ni1.c @@ -22,6 +22,7 @@ #include "isdnl3.h" #include "l3ni1.h" #include +#include extern char *HiSax_getrev(const char *revision); static const char *ni1_revision = "$Revision: 2.8.2.3 $"; diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c index 02c6fbaeccf8..5d7f0f2ff9b9 100644 --- a/drivers/isdn/hisax/netjet.c +++ b/drivers/isdn/hisax/netjet.c @@ -21,6 +21,7 @@ #include "isdnl1.h" #include #include +#include #include #include "netjet.h" diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c index 95b1cdd97958..e56e5af889b6 100644 --- a/drivers/isdn/hisax/st5481_b.c +++ b/drivers/isdn/hisax/st5481_b.c @@ -11,8 +11,8 @@ */ #include +#include #include -#include #include #include #include "st5481.h" diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c index 39e8e49cfd2d..b7876b19fe73 100644 --- a/drivers/isdn/hisax/st5481_d.c +++ b/drivers/isdn/hisax/st5481_d.c @@ -11,8 +11,8 @@ */ #include +#include #include -#include #include #include "st5481.h" diff --git a/drivers/isdn/hisax/tei.c b/drivers/isdn/hisax/tei.c index 6e65424f1f04..f4cb178b0666 100644 --- a/drivers/isdn/hisax/tei.c +++ b/drivers/isdn/hisax/tei.c @@ -17,6 +17,7 @@ #include "hisax.h" #include "isdnl2.h" +#include #include #include diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c index 9d6e864023fe..e2cfb6f5aa42 100644 --- a/drivers/isdn/hisax/w6692.c +++ b/drivers/isdn/hisax/w6692.c @@ -16,6 +16,7 @@ #include "isdnl1.h" #include #include +#include /* table entry in the PCI devices list */ typedef struct { diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c index fe874afa4f81..6299b06ae009 100644 --- a/drivers/isdn/hysdn/hycapi.c +++ b/drivers/isdn/hysdn/hycapi.c @@ -17,6 +17,7 @@ #include #include #include +#include #define VER_DRIVER 0 #define VER_CARDTYPE 1 diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c index 90b35e1a4b7e..80966462d6dc 100644 --- a/drivers/isdn/hysdn/hysdn_procconf.c +++ b/drivers/isdn/hysdn/hysdn_procconf.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c index 8bcae28c4409..e83f6fda32fe 100644 --- a/drivers/isdn/hysdn/hysdn_proclog.c +++ b/drivers/isdn/hysdn/hysdn_proclog.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "hysdn_defs.h" diff --git a/drivers/isdn/i4l/isdn_audio.c b/drivers/isdn/i4l/isdn_audio.c index fb350c567c6b..861bdf3421f2 100644 --- a/drivers/isdn/i4l/isdn_audio.c +++ b/drivers/isdn/i4l/isdn_audio.c @@ -12,6 +12,7 @@ */ #include +#include #include "isdn_audio.h" #include "isdn_common.h" diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index 00c60e2e0ff7..70044ee4b228 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index 507e13d9a57c..8c85d1e88cc6 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c @@ -23,6 +23,7 @@ */ #include +#include #include #include #include diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c index 45df6675e8ed..f37b8f68d0aa 100644 --- a/drivers/isdn/i4l/isdn_ppp.c +++ b/drivers/isdn/i4l/isdn_ppp.c @@ -12,6 +12,7 @@ #include #include #include +#include #ifdef CONFIG_IPPP_FILTER #include #endif diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 2881a66c1aa9..fc8454d2eea5 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -12,6 +12,7 @@ #undef ISDN_TTY_STAT_DEBUG #include +#include #include #include #include "isdn_common.h" diff --git a/drivers/isdn/i4l/isdn_x25iface.c b/drivers/isdn/i4l/isdn_x25iface.c index 8b3efc243161..efcf1f9327e5 100644 --- a/drivers/isdn/i4l/isdn_x25iface.c +++ b/drivers/isdn/i4l/isdn_x25iface.c @@ -20,6 +20,7 @@ /* #include */ #include #include +#include #include #include #include "isdn_x25iface.h" diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c index bf7997abc4ac..2e847a90bad0 100644 --- a/drivers/isdn/icn/icn.c +++ b/drivers/isdn/icn/icn.c @@ -12,6 +12,7 @@ #include "icn.h" #include #include +#include #include static int portbase = ICN_BASEADDR; diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index a335c85a736e..b8a1098b66ed 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include "isdnloop.h" diff --git a/drivers/isdn/mISDN/clock.c b/drivers/isdn/mISDN/clock.c index f1bbc88763b2..1fa629b3b940 100644 --- a/drivers/isdn/mISDN/clock.c +++ b/drivers/isdn/mISDN/clock.c @@ -33,6 +33,7 @@ * */ +#include #include #include #include diff --git a/drivers/isdn/mISDN/core.c b/drivers/isdn/mISDN/core.c index 21d34be5af6a..afeebb00fe0b 100644 --- a/drivers/isdn/mISDN/core.c +++ b/drivers/isdn/mISDN/core.c @@ -12,6 +12,7 @@ * */ +#include #include #include #include diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c index 9c7c0d1ba55f..713ef2b805a2 100644 --- a/drivers/isdn/mISDN/dsp_cmx.c +++ b/drivers/isdn/mISDN/dsp_cmx.c @@ -124,6 +124,7 @@ /* delay.h is required for hw_lock.h */ +#include #include #include #include diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c index 6eac588e0a37..6f5b54864283 100644 --- a/drivers/isdn/mISDN/dsp_core.c +++ b/drivers/isdn/mISDN/dsp_core.c @@ -154,6 +154,7 @@ */ #include +#include #include #include #include diff --git a/drivers/isdn/mISDN/dsp_pipeline.c b/drivers/isdn/mISDN/dsp_pipeline.c index e9941678edfa..621f31007095 100644 --- a/drivers/isdn/mISDN/dsp_pipeline.c +++ b/drivers/isdn/mISDN/dsp_pipeline.c @@ -25,6 +25,7 @@ */ #include +#include #include #include #include diff --git a/drivers/isdn/mISDN/dsp_tones.c b/drivers/isdn/mISDN/dsp_tones.c index 1debf53670de..7dbe54ed1deb 100644 --- a/drivers/isdn/mISDN/dsp_tones.c +++ b/drivers/isdn/mISDN/dsp_tones.c @@ -8,6 +8,7 @@ * */ +#include #include #include #include "core.h" diff --git a/drivers/isdn/mISDN/hwchannel.c b/drivers/isdn/mISDN/hwchannel.c index e8049be552aa..307bd6e8988b 100644 --- a/drivers/isdn/mISDN/hwchannel.c +++ b/drivers/isdn/mISDN/hwchannel.c @@ -15,6 +15,7 @@ * */ +#include #include #include diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c index 325b1ad7d4b8..22f38e48ac4e 100644 --- a/drivers/isdn/mISDN/l1oip_core.c +++ b/drivers/isdn/mISDN/l1oip_core.c @@ -233,6 +233,7 @@ socket process and create a new one. #include #include #include +#include #include #include "core.h" #include "l1oip.h" diff --git a/drivers/isdn/mISDN/layer1.c b/drivers/isdn/mISDN/layer1.c index e826eeb1ecec..ac4aa18c632b 100644 --- a/drivers/isdn/mISDN/layer1.c +++ b/drivers/isdn/mISDN/layer1.c @@ -16,6 +16,7 @@ */ +#include #include #include #include "core.h" diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c index e17f0044e0b6..c97371788764 100644 --- a/drivers/isdn/mISDN/layer2.c +++ b/drivers/isdn/mISDN/layer2.c @@ -16,6 +16,7 @@ */ #include +#include #include "core.h" #include "fsm.h" #include "layer2.h" diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c index fcfe17a19a61..3232206406b1 100644 --- a/drivers/isdn/mISDN/socket.c +++ b/drivers/isdn/mISDN/socket.c @@ -16,6 +16,7 @@ */ #include +#include #include "core.h" static u_int *debug; diff --git a/drivers/isdn/mISDN/stack.c b/drivers/isdn/mISDN/stack.c index 0d05ec43012c..b159bd59e64e 100644 --- a/drivers/isdn/mISDN/stack.c +++ b/drivers/isdn/mISDN/stack.c @@ -15,6 +15,7 @@ * */ +#include #include #include #include diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c index 6d4da6095885..34e898fe2f4f 100644 --- a/drivers/isdn/mISDN/tei.c +++ b/drivers/isdn/mISDN/tei.c @@ -16,6 +16,7 @@ */ #include "layer2.h" #include +#include #include "core.h" #define ID_REQUEST 1 diff --git a/drivers/isdn/mISDN/timerdev.c b/drivers/isdn/mISDN/timerdev.c index 5b7e9bf514f1..8785004e85e0 100644 --- a/drivers/isdn/mISDN/timerdev.c +++ b/drivers/isdn/mISDN/timerdev.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include diff --git a/drivers/isdn/pcbit/callbacks.c b/drivers/isdn/pcbit/callbacks.c index 43ecd0f54235..976143b2346d 100644 --- a/drivers/isdn/pcbit/callbacks.c +++ b/drivers/isdn/pcbit/callbacks.c @@ -19,7 +19,6 @@ #include #include -#include #include #include diff --git a/drivers/isdn/pcbit/edss1.c b/drivers/isdn/pcbit/edss1.c index 37e9626cebf6..d5920ae22d73 100644 --- a/drivers/isdn/pcbit/edss1.c +++ b/drivers/isdn/pcbit/edss1.c @@ -19,7 +19,6 @@ #include #include -#include #include #include diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c index 5a0774880d56..ca710ab278ec 100644 --- a/drivers/isdn/sc/init.c +++ b/drivers/isdn/sc/init.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "includes.h" #include "hardware.h" #include "card.h" -- cgit v1.2.2 From b91ecb0027c7171c83d7cf443a22c39b1fde6d83 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Fri, 16 Apr 2010 12:08:58 +0000 Subject: gigaset: include cleanup cleanup Commit 5a0e3ad causes slab.h to be included twice in many of the Gigaset driver's source files, first via the common include file gigaset.h and then a second time directly. Drop the spares, and use the opportunity to clean up a few more similar cases. Impact: cleanup, no functional change Signed-off-by: Tilman Schmidt CC: Tejun Heo Acked-by: Tejun Heo Signed-off-by: David S. Miller --- drivers/isdn/gigaset/bas-gigaset.c | 5 ----- drivers/isdn/gigaset/capi.c | 2 -- drivers/isdn/gigaset/common.c | 2 -- drivers/isdn/gigaset/gigaset.h | 2 +- drivers/isdn/gigaset/i4l.c | 1 - drivers/isdn/gigaset/interface.c | 1 - drivers/isdn/gigaset/proc.c | 1 - drivers/isdn/gigaset/ser-gigaset.c | 3 --- drivers/isdn/gigaset/usb-gigaset.c | 4 ---- 9 files changed, 1 insertion(+), 20 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 0be15c70c16d..47a5ffec55a3 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -14,11 +14,6 @@ */ #include "gigaset.h" - -#include -#include -#include -#include #include #include #include diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index eb7e27105a82..964a55fb1486 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -12,8 +12,6 @@ */ #include "gigaset.h" -#include -#include #include #include #include diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 0b39b387c125..f6f45f221920 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -14,10 +14,8 @@ */ #include "gigaset.h" -#include #include #include -#include /* Version Information */ #define DRIVER_AUTHOR "Hansjoerg Lipp , Tilman Schmidt , Stefan Eilers" diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 9ef5b0463fd5..d32efb651042 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -22,9 +22,9 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c index c99fb9790a13..c22e5ace8276 100644 --- a/drivers/isdn/gigaset/i4l.c +++ b/drivers/isdn/gigaset/i4l.c @@ -15,7 +15,6 @@ #include "gigaset.h" #include -#include #define HW_HDR_LEN 2 /* Header size used to store ack info */ diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index f0dc6c9cc283..c9f28dd40d5c 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -13,7 +13,6 @@ #include "gigaset.h" #include -#include #include /*** our ioctls ***/ diff --git a/drivers/isdn/gigaset/proc.c b/drivers/isdn/gigaset/proc.c index b69f73a0668f..b943efbff44d 100644 --- a/drivers/isdn/gigaset/proc.c +++ b/drivers/isdn/gigaset/proc.c @@ -14,7 +14,6 @@ */ #include "gigaset.h" -#include static ssize_t show_cidmode(struct device *dev, struct device_attribute *attr, char *buf) diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index 8b0afd203a07..e96c0586886c 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c @@ -11,13 +11,10 @@ */ #include "gigaset.h" - #include #include #include -#include #include -#include /* Version Information */ #define DRIVER_AUTHOR "Tilman Schmidt" diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index 9430a2bbb523..76dbb20f3065 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c @@ -16,10 +16,6 @@ */ #include "gigaset.h" - -#include -#include -#include #include #include #include -- cgit v1.2.2 From 76e506a754c9519ba0a948b475a62f31fac8b599 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 19 Apr 2010 11:53:17 -0700 Subject: Fix ISDN/Gigaset build failure Commit b91ecb00 ("gigaset: include cleanup cleanup") removed an implicit sched.h inclusion that came in via slab.h, and caused various compile problems as a result. This should fix it. Reported-by: Ingo Molnar Signed-off-by: Linus Torvalds --- drivers/isdn/gigaset/gigaset.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index d32efb651042..05947f9c1849 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -20,6 +20,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#include #include #include #include -- cgit v1.2.2