diff options
Diffstat (limited to 'drivers/isdn')
28 files changed, 385 insertions, 734 deletions
diff --git a/drivers/isdn/act2000/act2000.h b/drivers/isdn/act2000/act2000.h index d4c5051..88c9423 100644 --- a/drivers/isdn/act2000/act2000.h +++ b/drivers/isdn/act2000/act2000.h @@ -141,9 +141,9 @@ typedef struct irq_data_isa { __u8 rcvhdr[8]; } irq_data_isa; -typedef union irq_data { +typedef union act2000_irq_data { irq_data_isa isa; -} irq_data; +} act2000_irq_data; /* * Per card driver data @@ -176,7 +176,7 @@ typedef struct act2000_card { char *status_buf_read; char *status_buf_write; char *status_buf_end; - irq_data idat; /* Data used for IRQ handler */ + act2000_irq_data idat; /* Data used for IRQ handler */ isdn_if interface; /* Interface to upper layer */ char regname[35]; /* Name used for request_region */ } act2000_card; diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c index 2978bda..e54e79d 100644 --- a/drivers/isdn/capi/capidrv.c +++ b/drivers/isdn/capi/capidrv.c @@ -1515,8 +1515,13 @@ static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep) while (*s) { int digit1 = 0; int digit2 = 0; - if (!isdigit(*s)) return -3; - while (isdigit(*s)) { digit1 = digit1*10 + (*s - '0'); s++; } + char *endp; + + digit1 = simple_strtoul(s, &endp, 10); + if (s == endp) + return -3; + s = endp; + if (digit1 <= 0 || digit1 > 30) return -4; if (*s == 0 || *s == ',' || *s == ' ') { bmask |= (1 << digit1); @@ -1526,8 +1531,12 @@ static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep) } if (*s != '-') return -5; s++; - if (!isdigit(*s)) return -3; - while (isdigit(*s)) { digit2 = digit2*10 + (*s - '0'); s++; } + + digit2 = simple_strtoul(s, &endp, 10); + if (s == endp) + return -3; + s = endp; + if (digit2 <= 0 || digit2 > 30) return -4; if (*s == 0 || *s == ',' || *s == ' ') { if (digit1 > digit2) diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index b054494..3acf94c 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -98,6 +98,16 @@ static inline struct capi_ctr *get_capi_ctr_by_nr(u16 contr) return capi_controller[contr - 1]; } +static inline struct capi20_appl *__get_capi_appl_by_nr(u16 applid) +{ + lockdep_assert_held(&capi_controller_lock); + + if (applid - 1 >= CAPI_MAXAPPL) + return NULL; + + return capi_applications[applid - 1]; +} + static inline struct capi20_appl *get_capi_appl_by_nr(u16 applid) { if (applid - 1 >= CAPI_MAXAPPL) @@ -185,10 +195,9 @@ static void notify_up(u32 contr) ctr->state = CAPI_CTR_RUNNING; for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { - ap = get_capi_appl_by_nr(applid); - if (!ap) - continue; - register_appl(ctr, applid, &ap->rparam); + ap = __get_capi_appl_by_nr(applid); + if (ap) + register_appl(ctr, applid, &ap->rparam); } wake_up_interruptible_all(&ctr->state_wait_queue); @@ -215,7 +224,7 @@ static void ctr_down(struct capi_ctr *ctr, int new_state) memset(ctr->serial, 0, sizeof(ctr->serial)); for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { - ap = get_capi_appl_by_nr(applid); + ap = __get_capi_appl_by_nr(applid); if (ap) capi_ctr_put(ctr); } diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c index 70cf6ba..48e6d22 100644 --- a/drivers/isdn/divert/isdn_divert.c +++ b/drivers/isdn/divert/isdn_divert.c @@ -77,7 +77,7 @@ static void deflect_timer_expire(ulong arg) case DEFLECT_ALERT: cs->ics.command = ISDN_CMD_REDIR; /* protocol */ - strcpy(cs->ics.parm.setup.phone,cs->deflect_dest); + strlcpy(cs->ics.parm.setup.phone, cs->deflect_dest, sizeof(cs->ics.parm.setup.phone)); strcpy(cs->ics.parm.setup.eazmsn,"Testtext delayed"); divert_if.ll_cmd(&cs->ics); spin_lock_irqsave(&divert_lock, flags); @@ -251,7 +251,7 @@ int deflect_extern_action(u_char cmd, ulong callid, char *to_nr) case 2: /* redir */ del_timer(&cs->timer); - strcpy(cs->ics.parm.setup.phone, to_nr); + strlcpy(cs->ics.parm.setup.phone, to_nr, sizeof(cs->ics.parm.setup.phone)); strcpy(cs->ics.parm.setup.eazmsn, "Testtext manual"); ic.command = ISDN_CMD_REDIR; if ((i = divert_if.ll_cmd(&ic))) @@ -480,7 +480,7 @@ static int isdn_divert_icall(isdn_ctrl *ic) if (!cs->timer.expires) { strcpy(ic->parm.setup.eazmsn,"Testtext direct"); ic->parm.setup.screen = dv->rule.screen; - strcpy(ic->parm.setup.phone,dv->rule.to_nr); + strlcpy(ic->parm.setup.phone, dv->rule.to_nr, sizeof(ic->parm.setup.phone)); cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); retval = 5; diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 707d9c9..178942a 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -109,6 +109,9 @@ struct bas_cardstate { struct urb *urb_int_in; /* URB for interrupt pipe */ unsigned char *int_in_buf; + struct work_struct int_in_wq; /* for usb_clear_halt() */ + struct timer_list timer_int_in; /* int read retry delay */ + int retry_int_in; spinlock_t lock; /* locks all following */ int basstate; /* bitmap (BS_*) */ @@ -169,7 +172,7 @@ static char *get_usb_rcmsg(int rc) case -EAGAIN: return "start frame too early or too much scheduled"; case -EFBIG: - return "too many isochronous frames requested"; + return "too many isoc frames requested"; case -EPIPE: return "endpoint stalled"; case -EMSGSIZE: @@ -200,13 +203,13 @@ static char *get_usb_statmsg(int status) case -ENOENT: return "unlinked (sync)"; case -EINPROGRESS: - return "pending"; + return "URB still pending"; case -EPROTO: - return "bit stuffing error, timeout, or unknown USB error"; + return "bitstuff error, timeout, or unknown USB error"; case -EILSEQ: return "CRC mismatch, timeout, or unknown USB error"; case -ETIME: - return "timed out"; + return "USB response timeout"; case -EPIPE: return "endpoint stalled"; case -ECOMM: @@ -214,15 +217,15 @@ static char *get_usb_statmsg(int status) case -ENOSR: return "OUT buffer underrun"; case -EOVERFLOW: - return "too much data"; + return "endpoint babble"; case -EREMOTEIO: - return "short packet detected"; + return "short packet"; case -ENODEV: return "device removed"; case -EXDEV: - return "partial isochronous transfer"; + return "partial isoc transfer"; case -EINVAL: - return "invalid argument"; + return "ISO madness"; case -ECONNRESET: return "unlinked (async)"; case -ESHUTDOWN: @@ -350,7 +353,7 @@ static inline void error_hangup(struct bc_state *bcs) * reset Gigaset device because of an unrecoverable error * This function may be called from any context, and takes care of * scheduling the necessary actions for execution outside of interrupt context. - * cs->lock must not be held. + * cs->hw.bas->lock must not be held. * argument: * controller state structure */ @@ -358,7 +361,9 @@ static inline void error_reset(struct cardstate *cs) { /* reset interrupt pipe to recover (ignore errors) */ update_basstate(cs->hw.bas, BS_RESETTING, 0); - req_submit(cs->bcs, HD_RESET_INTERRUPT_PIPE, 0, BAS_TIMEOUT); + if (req_submit(cs->bcs, HD_RESET_INTERRUPT_PIPE, 0, BAS_TIMEOUT)) + /* submission failed, escalate to USB port reset */ + usb_queue_reset_device(cs->hw.bas->interface); } /* check_pending @@ -438,23 +443,27 @@ static void cmd_in_timeout(unsigned long data) return; } - if (ucs->retry_cmd_in++ < BAS_RETRY) { - dev_notice(cs->dev, "control read: timeout, retry %d\n", - ucs->retry_cmd_in); - rc = atread_submit(cs, BAS_TIMEOUT); - if (rc >= 0 || rc == -ENODEV) - /* resubmitted or disconnected */ - /* - bypass regular exit block */ - return; - } else { + if (ucs->retry_cmd_in++ >= BAS_RETRY) { dev_err(cs->dev, "control read: timeout, giving up after %d tries\n", ucs->retry_cmd_in); + kfree(ucs->rcvbuf); + ucs->rcvbuf = NULL; + ucs->rcvbuf_size = 0; + error_reset(cs); + return; + } + + gig_dbg(DEBUG_USBREQ, "%s: timeout, retry %d", + __func__, ucs->retry_cmd_in); + rc = atread_submit(cs, BAS_TIMEOUT); + if (rc < 0) { + kfree(ucs->rcvbuf); + ucs->rcvbuf = NULL; + ucs->rcvbuf_size = 0; + if (rc != -ENODEV) + error_reset(cs); } - kfree(ucs->rcvbuf); - ucs->rcvbuf = NULL; - ucs->rcvbuf_size = 0; - error_reset(cs); } /* read_ctrl_callback @@ -470,18 +479,11 @@ static void read_ctrl_callback(struct urb *urb) struct cardstate *cs = inbuf->cs; struct bas_cardstate *ucs = cs->hw.bas; int status = urb->status; - int have_data = 0; unsigned numbytes; int rc; update_basstate(ucs, 0, BS_ATRDPEND); wake_up(&ucs->waitqueue); - - if (!ucs->rcvbuf_size) { - dev_warn(cs->dev, "%s: no receive in progress\n", __func__); - return; - } - del_timer(&ucs->timer_cmd_in); switch (status) { @@ -495,19 +497,10 @@ static void read_ctrl_callback(struct urb *urb) numbytes = ucs->rcvbuf_size; } - /* copy received bytes to inbuf */ - have_data = gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes); - - if (unlikely(numbytes < ucs->rcvbuf_size)) { - /* incomplete - resubmit for remaining bytes */ - ucs->rcvbuf_size -= numbytes; - ucs->retry_cmd_in = 0; - rc = atread_submit(cs, BAS_TIMEOUT); - if (rc >= 0 || rc == -ENODEV) - /* resubmitted or disconnected */ - /* - bypass regular exit block */ - return; - error_reset(cs); + /* copy received bytes to inbuf, notify event layer */ + if (gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes)) { + gig_dbg(DEBUG_INTR, "%s-->BH", __func__); + gigaset_schedule_event(cs); } break; @@ -516,37 +509,32 @@ static void read_ctrl_callback(struct urb *urb) case -EINPROGRESS: /* pending */ case -ENODEV: /* device removed */ case -ESHUTDOWN: /* device shut down */ - /* no action necessary */ + /* no further action necessary */ gig_dbg(DEBUG_USBREQ, "%s: %s", __func__, get_usb_statmsg(status)); break; - default: /* severe trouble */ - dev_warn(cs->dev, "control read: %s\n", - get_usb_statmsg(status)); + default: /* other errors: retry */ if (ucs->retry_cmd_in++ < BAS_RETRY) { - dev_notice(cs->dev, "control read: retry %d\n", - ucs->retry_cmd_in); + gig_dbg(DEBUG_USBREQ, "%s: %s, retry %d", __func__, + get_usb_statmsg(status), ucs->retry_cmd_in); rc = atread_submit(cs, BAS_TIMEOUT); - if (rc >= 0 || rc == -ENODEV) - /* resubmitted or disconnected */ - /* - bypass regular exit block */ + if (rc >= 0) + /* successfully resubmitted, skip freeing */ return; - } else { - dev_err(cs->dev, - "control read: giving up after %d tries\n", - ucs->retry_cmd_in); + if (rc == -ENODEV) + /* disconnect, no further action necessary */ + break; } + dev_err(cs->dev, "control read: %s, giving up after %d tries\n", + get_usb_statmsg(status), ucs->retry_cmd_in); error_reset(cs); } + /* read finished, free buffer */ kfree(ucs->rcvbuf); ucs->rcvbuf = NULL; ucs->rcvbuf_size = 0; - if (have_data) { - gig_dbg(DEBUG_INTR, "%s-->BH", __func__); - gigaset_schedule_event(cs); - } } /* atread_submit @@ -605,14 +593,67 @@ static int atread_submit(struct cardstate *cs, int timeout) if (timeout > 0) { gig_dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout); - ucs->timer_cmd_in.expires = jiffies + timeout * HZ / 10; - ucs->timer_cmd_in.data = (unsigned long) cs; - ucs->timer_cmd_in.function = cmd_in_timeout; - add_timer(&ucs->timer_cmd_in); + mod_timer(&ucs->timer_cmd_in, jiffies + timeout * HZ / 10); } return 0; } +/* int_in_work + * workqueue routine to clear halt on interrupt in endpoint + */ + +static void int_in_work(struct work_struct *work) +{ + struct bas_cardstate *ucs = + container_of(work, struct bas_cardstate, int_in_wq); + struct urb *urb = ucs->urb_int_in; + struct cardstate *cs = urb->context; + int rc; + + /* clear halt condition */ + rc = usb_clear_halt(ucs->udev, urb->pipe); + gig_dbg(DEBUG_USBREQ, "clear_halt: %s", get_usb_rcmsg(rc)); + if (rc == 0) + /* success, resubmit interrupt read URB */ + rc = usb_submit_urb(urb, GFP_ATOMIC); + if (rc != 0 && rc != -ENODEV) { + dev_err(cs->dev, "clear halt failed: %s\n", get_usb_rcmsg(rc)); + rc = usb_lock_device_for_reset(ucs->udev, ucs->interface); + if (rc == 0) { + rc = usb_reset_device(ucs->udev); + usb_unlock_device(ucs->udev); + } + } + ucs->retry_int_in = 0; +} + +/* int_in_resubmit + * timer routine for interrupt read delayed resubmit + * argument: + * controller state structure + */ +static void int_in_resubmit(unsigned long data) +{ + struct cardstate *cs = (struct cardstate *) data; + struct bas_cardstate *ucs = cs->hw.bas; + int rc; + + if (ucs->retry_int_in++ >= BAS_RETRY) { + dev_err(cs->dev, "interrupt read: giving up after %d tries\n", + ucs->retry_int_in); + usb_queue_reset_device(ucs->interface); + return; + } + + gig_dbg(DEBUG_USBREQ, "%s: retry %d", __func__, ucs->retry_int_in); + rc = usb_submit_urb(ucs->urb_int_in, GFP_ATOMIC); + if (rc != 0 && rc != -ENODEV) { + dev_err(cs->dev, "could not resubmit interrupt URB: %s\n", + get_usb_rcmsg(rc)); + usb_queue_reset_device(ucs->interface); + } +} + /* read_int_callback * USB completion handler for interrupt pipe input * called by the USB subsystem in interrupt context @@ -633,19 +674,29 @@ static void read_int_callback(struct urb *urb) switch (status) { case 0: /* success */ + ucs->retry_int_in = 0; break; + case -EPIPE: /* endpoint stalled */ + schedule_work(&ucs->int_in_wq); + /* fall through */ case -ENOENT: /* cancelled */ case -ECONNRESET: /* cancelled (async) */ case -EINPROGRESS: /* pending */ - /* ignore silently */ + case -ENODEV: /* device removed */ + case -ESHUTDOWN: /* device shut down */ + /* no further action necessary */ gig_dbg(DEBUG_USBREQ, "%s: %s", __func__, get_usb_statmsg(status)); return; - case -ENODEV: /* device removed */ - case -ESHUTDOWN: /* device shut down */ - gig_dbg(DEBUG_USBREQ, "%s: device disconnected", __func__); + case -EPROTO: /* protocol error or unplug */ + case -EILSEQ: + case -ETIME: + /* resubmit after delay */ + gig_dbg(DEBUG_USBREQ, "%s: %s", + __func__, get_usb_statmsg(status)); + mod_timer(&ucs->timer_int_in, jiffies + HZ / 10); return; - default: /* severe trouble */ + default: /* other errors: just resubmit */ dev_warn(cs->dev, "interrupt read: %s\n", get_usb_statmsg(status)); goto resubmit; @@ -723,6 +774,13 @@ static void read_int_callback(struct urb *urb) break; } spin_lock_irqsave(&cs->lock, flags); + if (ucs->basstate & BS_ATRDPEND) { + spin_unlock_irqrestore(&cs->lock, flags); + dev_warn(cs->dev, + "HD_RECEIVEATDATA_ACK(%d) during HD_READ_ATMESSAGE(%d) ignored\n", + l, ucs->rcvbuf_size); + break; + } if (ucs->rcvbuf_size) { /* throw away previous buffer - we have no queue */ dev_err(cs->dev, @@ -735,7 +793,6 @@ static void read_int_callback(struct urb *urb) if (ucs->rcvbuf == NULL) { spin_unlock_irqrestore(&cs->lock, flags); dev_err(cs->dev, "out of memory receiving AT data\n"); - error_reset(cs); break; } ucs->rcvbuf_size = l; @@ -745,13 +802,10 @@ static void read_int_callback(struct urb *urb) kfree(ucs->rcvbuf); ucs->rcvbuf = NULL; ucs->rcvbuf_size = 0; - if (rc != -ENODEV) { - spin_unlock_irqrestore(&cs->lock, flags); - error_reset(cs); - break; - } } spin_unlock_irqrestore(&cs->lock, flags); + if (rc < 0 && rc != -ENODEV) + error_reset(cs); break; case HD_RESET_INTERRUPT_PIPE_ACK: @@ -818,6 +872,7 @@ static void read_iso_callback(struct urb *urb) tasklet_hi_schedule(&ubc->rcvd_tasklet); } else { /* tasklet still busy, drop data and resubmit URB */ + gig_dbg(DEBUG_ISO, "%s: overrun", __func__); ubc->loststatus = status; for (i = 0; i < BAS_NUMFRAMES; i++) { ubc->isoinlost += urb->iso_frame_desc[i].actual_length; @@ -833,13 +888,11 @@ static void read_iso_callback(struct urb *urb) urb->dev = bcs->cs->hw.bas->udev; urb->transfer_flags = URB_ISO_ASAP; urb->number_of_packets = BAS_NUMFRAMES; - gig_dbg(DEBUG_ISO, "%s: isoc read overrun/resubmit", - __func__); rc = usb_submit_urb(urb, GFP_ATOMIC); if (unlikely(rc != 0 && rc != -ENODEV)) { dev_err(bcs->cs->dev, - "could not resubmit isochronous read " - "URB: %s\n", get_usb_rcmsg(rc)); + "could not resubmit isoc read URB: %s\n", + get_usb_rcmsg(rc)); dump_urb(DEBUG_ISO, "isoc read", urb); error_hangup(bcs); } @@ -1081,7 +1134,7 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) gig_dbg(DEBUG_ISO, "%s: disconnected", __func__); else dev_err(ucx->bcs->cs->dev, - "could not submit isochronous write URB: %s\n", + "could not submit isoc write URB: %s\n", get_usb_rcmsg(rc)); return rc; } @@ -1126,7 +1179,7 @@ static void write_iso_tasklet(unsigned long data) ubc->isooutovfl = NULL; spin_unlock_irqrestore(&ubc->isooutlock, flags); if (ovfl) { - dev_err(cs->dev, "isochronous write buffer underrun\n"); + dev_err(cs->dev, "isoc write underrun\n"); error_hangup(bcs); break; } @@ -1151,7 +1204,7 @@ static void write_iso_tasklet(unsigned long data) if (next) { /* couldn't put it back */ dev_err(cs->dev, - "losing isochronous write URB\n"); + "losing isoc write URB\n"); error_hangup(bcs); } } @@ -1178,10 +1231,10 @@ static void write_iso_tasklet(unsigned long data) if (ifd->status || ifd->actual_length != ifd->length) { dev_warn(cs->dev, - "isochronous write: frame %d: %s, " - "only %d of %d bytes sent\n", - i, get_usb_statmsg(ifd->status), - ifd->actual_length, ifd->length); + "isoc write: frame %d[%d/%d]: %s\n", + i, ifd->actual_length, + ifd->length, + get_usb_statmsg(ifd->status)); offset = (ifd->offset + ifd->actual_length) % BAS_OUTBUFSIZE; @@ -1190,11 +1243,11 @@ static void write_iso_tasklet(unsigned long data) } break; case -EPIPE: /* stall - probably underrun */ - dev_err(cs->dev, "isochronous write stalled\n"); + dev_err(cs->dev, "isoc write: stalled\n"); error_hangup(bcs); break; - default: /* severe trouble */ - dev_warn(cs->dev, "isochronous write: %s\n", + default: /* other errors */ + dev_warn(cs->dev, "isoc write: %s\n", get_usb_statmsg(status)); } @@ -1250,6 +1303,7 @@ static void read_iso_tasklet(unsigned long data) struct cardstate *cs = bcs->cs; struct urb *urb; int status; + struct usb_iso_packet_descriptor *ifd; char *rcvbuf; unsigned long flags; int totleft, numbytes, offset, frame, rc; @@ -1267,8 +1321,7 @@ static void read_iso_tasklet(unsigned long data) ubc->isoindone = NULL; if (unlikely(ubc->loststatus != -EINPROGRESS)) { dev_warn(cs->dev, - "isochronous read overrun, " - "dropped URB with status: %s, %d bytes lost\n", + "isoc read overrun, URB dropped (status: %s, %d bytes)\n", get_usb_statmsg(ubc->loststatus), ubc->isoinlost); ubc->loststatus = -EINPROGRESS; @@ -1298,11 +1351,11 @@ static void read_iso_tasklet(unsigned long data) __func__, get_usb_statmsg(status)); continue; /* -> skip */ case -EPIPE: - dev_err(cs->dev, "isochronous read stalled\n"); + dev_err(cs->dev, "isoc read: stalled\n"); error_hangup(bcs); continue; /* -> skip */ - default: /* severe trouble */ - dev_warn(cs->dev, "isochronous read: %s\n", + default: /* other error */ + dev_warn(cs->dev, "isoc read: %s\n", get_usb_statmsg(status)); goto error; } @@ -1310,40 +1363,52 @@ static void read_iso_tasklet(unsigned long data) rcvbuf = urb->transfer_buffer; totleft = urb->actual_length; for (frame = 0; totleft > 0 && frame < BAS_NUMFRAMES; frame++) { - numbytes = urb->iso_frame_desc[frame].actual_length; - if (unlikely(urb->iso_frame_desc[frame].status)) + ifd = &urb->iso_frame_desc[frame]; + numbytes = ifd->actual_length; + switch (ifd->status) { + case 0: /* success */ + break; + case -EPROTO: /* protocol error or unplug */ + case -EILSEQ: + case -ETIME: + /* probably just disconnected, ignore */ + gig_dbg(DEBUG_ISO, + "isoc read: frame %d[%d]: %s\n", + frame, numbytes, + get_usb_statmsg(ifd->status)); + break; + default: /* other error */ + /* report, assume transferred bytes are ok */ dev_warn(cs->dev, - "isochronous read: frame %d[%d]: %s\n", + "isoc read: frame %d[%d]: %s\n", frame, numbytes, - get_usb_statmsg( - urb->iso_frame_desc[frame].status)); + get_usb_statmsg(ifd->status)); + } if (unlikely(numbytes > BAS_MAXFRAME)) dev_warn(cs->dev, - "isochronous read: frame %d: " - "numbytes (%d) > BAS_MAXFRAME\n", - frame, numbytes); + "isoc read: frame %d[%d]: %s\n", + frame, numbytes, + "exceeds max frame size"); if (unlikely(numbytes > totleft)) { dev_warn(cs->dev, - "isochronous read: frame %d: " - "numbytes (%d) > totleft (%d)\n", - frame, numbytes, totleft); + "isoc read: frame %d[%d]: %s\n", + frame, numbytes, + "exceeds total transfer length"); numbytes = totleft; } - offset = urb->iso_frame_desc[frame].offset; + offset = ifd->offset; if (unlikely(offset + numbytes > BAS_INBUFSIZE)) { dev_warn(cs->dev, - "isochronous read: frame %d: " - "offset (%d) + numbytes (%d) " - "> BAS_INBUFSIZE\n", - frame, offset, numbytes); + "isoc read: frame %d[%d]: %s\n", + frame, numbytes, + "exceeds end of buffer"); numbytes = BAS_INBUFSIZE - offset; } gigaset_isoc_receive(rcvbuf + offset, numbytes, bcs); totleft -= numbytes; } if (unlikely(totleft > 0)) - dev_warn(cs->dev, - "isochronous read: %d data bytes missing\n", + dev_warn(cs->dev, "isoc read: %d data bytes missing\n", totleft); error: @@ -1359,9 +1424,9 @@ error: rc = usb_submit_urb(urb, GFP_ATOMIC); if (unlikely(rc != 0 && rc != -ENODEV)) { dev_err(cs->dev, - "could not resubmit isochronous read URB: %s\n", + "could not resubmit isoc read URB: %s\n", get_usb_rcmsg(rc)); - dump_urb(DEBUG_ISO, "resubmit iso read", urb); + dump_urb(DEBUG_ISO, "resubmit isoc read", urb); error_hangup(bcs); } } @@ -1373,12 +1438,12 @@ error: /* req_timeout * timeout routine for control output request * argument: - * B channel control structure + * controller state structure */ static void req_timeout(unsigned long data) { - struct bc_state *bcs = (struct bc_state *) data; - struct bas_cardstate *ucs = bcs->cs->hw.bas; + struct cardstate *cs = (struct cardstate *) data; + struct bas_cardstate *ucs = cs->hw.bas; int pending; unsigned long flags; @@ -1395,38 +1460,44 @@ static void req_timeout(unsigned long data) break; case HD_OPEN_ATCHANNEL: - dev_err(bcs->cs->dev, "timeout opening AT channel\n"); - error_reset(bcs->cs); + dev_err(cs->dev, "timeout opening AT channel\n"); + error_reset(cs); break; - case HD_OPEN_B2CHANNEL: case HD_OPEN_B1CHANNEL: - dev_err(bcs->cs->dev, "timeout opening channel %d\n", - bcs->channel + 1); - error_hangup(bcs); + dev_err(cs->dev, "timeout opening channel 1\n"); + error_hangup(&cs->bcs[0]); + break; + + case HD_OPEN_B2CHANNEL: + dev_err(cs->dev, "timeout opening channel 2\n"); + error_hangup(&cs->bcs[1]); break; case HD_CLOSE_ATCHANNEL: - dev_err(bcs->cs->dev, "timeout closing AT channel\n"); - error_reset(bcs->cs); + dev_err(cs->dev, "timeout closing AT channel\n"); + error_reset(cs); break; - case HD_CLOSE_B2CHANNEL: case HD_CLOSE_B1CHANNEL: - dev_err(bcs->cs->dev, "timeout closing channel %d\n", - bcs->channel + 1); - error_reset(bcs->cs); + dev_err(cs->dev, "timeout closing channel 1\n"); + error_reset(cs); + break; + + case HD_CLOSE_B2CHANNEL: + dev_err(cs->dev, "timeout closing channel 2\n"); + error_reset(cs); break; case HD_RESET_INTERRUPT_PIPE: /* error recovery escalation */ - dev_err(bcs->cs->dev, + dev_err(cs->dev, "reset interrupt pipe timeout, attempting USB reset\n"); - usb_queue_reset_device(bcs->cs->hw.bas->interface); + usb_queue_reset_device(ucs->interface); break; default: - dev_warn(bcs->cs->dev, "request 0x%02x timed out, clearing\n", + dev_warn(cs->dev, "request 0x%02x timed out, clearing\n", pending); } @@ -1557,10 +1628,7 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout) if (timeout > 0) { gig_dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout); - ucs->timer_ctrl.expires = jiffies + timeout * HZ / 10; - ucs->timer_ctrl.data = (unsigned long) bcs; - ucs->timer_ctrl.function = req_timeout; - add_timer(&ucs->timer_ctrl); + mod_timer(&ucs->timer_ctrl, jiffies + timeout * HZ / 10); } spin_unlock_irqrestore(&ucs->lock, flags); @@ -1590,21 +1658,20 @@ static int gigaset_init_bchannel(struct bc_state *bcs) if (cs->hw.bas->basstate & BS_SUSPEND) { dev_notice(cs->dev, - "not starting isochronous I/O, " - "suspend in progress\n"); + "not starting isoc I/O, suspend in progress\n"); spin_unlock_irqrestore(&cs->lock, flags); return -EHOSTUNREACH; } ret = starturbs(bcs); if (ret < 0) { + spin_unlock_irqrestore(&cs->lock, flags); dev_err(cs->dev, - "could not start isochronous I/O for channel B%d: %s\n", + "could not start isoc I/O for channel B%d: %s\n", bcs->channel + 1, ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret)); if (ret != -ENODEV) error_hangup(bcs); - spin_unlock_irqrestore(&cs->lock, flags); return ret; } @@ -1614,11 +1681,11 @@ static int gigaset_init_bchannel(struct bc_state *bcs) dev_err(cs->dev, "could not open channel B%d\n", bcs->channel + 1); stopurbs(bcs->hw.bas); - if (ret != -ENODEV) - error_hangup(bcs); } spin_unlock_irqrestore(&cs->lock, flags); + if (ret < 0 && ret != -ENODEV) + error_hangup(bcs); return ret; } @@ -1826,10 +1893,7 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len) if (!(update_basstate(ucs, BS_ATTIMER, BS_ATREADY) & BS_ATTIMER)) { gig_dbg(DEBUG_OUTPUT, "setting ATREADY timeout of %d/10 secs", ATRDY_TIMEOUT); - ucs->timer_atrdy.expires = jiffies + ATRDY_TIMEOUT * HZ / 10; - ucs->timer_atrdy.data = (unsigned long) cs; - ucs->timer_atrdy.function = atrdy_timeout; - add_timer(&ucs->timer_atrdy); + mod_timer(&ucs->timer_atrdy, jiffies + ATRDY_TIMEOUT * HZ / 10); } return 0; } @@ -1914,6 +1978,28 @@ static int gigaset_write_cmd(struct cardstate *cs, struct cmdbuf_t *cb) * The next command will reopen the AT channel automatically. */ if (cb->len == 3 && !memcmp(cb->buf, "+++", 3)) { + /* If an HD_RECEIVEATDATA_ACK message remains unhandled + * because of an error, the base never sends another one. + * The response channel is thus effectively blocked. + * Closing and reopening the AT channel does *not* clear + * this condition. + * As a stopgap measure, submit a zero-length AT read + * before closing the AT channel. This has the undocumented + * effect of triggering a new HD_RECEIVEATDATA_ACK message + * from the base if necessary. + * The subsequent AT channel close then discards any pending + * messages. + */ + spin_lock_irqsave(&cs->lock, flags); + if (!(cs->hw.bas->basstate & BS_ATRDPEND)) { + kfree(cs->hw.bas->rcvbuf); + cs->hw.bas->rcvbuf = NULL; + cs->hw.bas->rcvbuf_size = 0; + cs->hw.bas->retry_cmd_in = 0; + atread_submit(cs, 0); + } + spin_unlock_irqrestore(&cs->lock, flags); + rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT); if (cb->wake_tasklet) tasklet_schedule(cb->wake_tasklet); @@ -2010,7 +2096,7 @@ static int gigaset_freebcshw(struct bc_state *bcs) /* kill URBs and tasklets before freeing - better safe than sorry */ ubc->running = 0; - gig_dbg(DEBUG_INIT, "%s: killing iso URBs", __func__); + gig_dbg(DEBUG_INIT, "%s: killing isoc URBs", __func__); for (i = 0; i < BAS_OUTURBS; ++i) { usb_kill_urb(ubc->isoouturbs[i].urb); usb_free_urb(ubc->isoouturbs[i].urb); @@ -2131,10 +2217,12 @@ static int gigaset_initcshw(struct cardstate *cs) ucs->pending = 0; ucs->basstate = 0; - init_timer(&ucs->timer_ctrl); - init_timer(&ucs->timer_atrdy); - init_timer(&ucs->timer_cmd_in); + setup_timer(&ucs->timer_ctrl, req_timeout, (unsigned long) cs); + setup_timer(&ucs->timer_atrdy, atrdy_timeout, (unsigned long) cs); + setup_timer(&ucs->timer_cmd_in, cmd_in_timeout, (unsigned long) cs); + setup_timer(&ucs->timer_int_in, int_in_resubmit, (unsigned long) cs); init_waitqueue_head(&ucs->waitqueue); + INIT_WORK(&ucs->int_in_wq, int_in_work); return 1; } @@ -2282,6 +2370,7 @@ static int gigaset_probe(struct usb_interface *interface, get_usb_rcmsg(rc)); goto error; } + ucs->retry_int_in = 0; /* tell the device that the driver is ready */ rc = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0); @@ -2334,10 +2423,12 @@ static void gigaset_disconnect(struct usb_interface *interface) /* stop driver (common part) */ gigaset_stop(cs); - /* stop timers and URBs, free ressources */ + /* stop delayed work and URBs, free ressources */ del_timer_sync(&ucs->timer_ctrl); del_timer_sync(&ucs->timer_atrdy); del_timer_sync(&ucs->timer_cmd_in); + del_timer_sync(&ucs->timer_int_in); + cancel_work_sync(&ucs->int_in_wq); freeurbs(cs); usb_set_intfdata(interface, NULL); kfree(ucs->rcvbuf); @@ -2400,10 +2491,14 @@ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) /* in case of timeout, proceed anyway */ } - /* kill all URBs and timers that might still be pending */ + /* kill all URBs and delayed work that might still be pending */ usb_kill_urb(ucs->urb_ctrl); usb_kill_urb(ucs->urb_int_in); del_timer_sync(&ucs->timer_ctrl); + del_timer_sync(&ucs->timer_atrdy); + del_timer_sync(&ucs->timer_cmd_in); + del_timer_sync(&ucs->timer_int_in); + cancel_work_sync(&ucs->int_in_wq); gig_dbg(DEBUG_SUSPEND, "suspend complete"); return 0; @@ -2425,6 +2520,7 @@ static int gigaset_resume(struct usb_interface *intf) get_usb_rcmsg(rc)); return rc; } + ucs->retry_int_in = 0; /* clear suspend flag to reallow activity */ update_basstate(ucs, 0, BS_SUSPEND); diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 3ca561e..db621db 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -1026,32 +1026,6 @@ struct cardstate *gigaset_get_cs_by_id(int id) return ret; } -void gigaset_debugdrivers(void) -{ - unsigned long flags; - static struct cardstate *cs; - struct gigaset_driver *drv; - unsigned i; - - spin_lock_irqsave(&driver_lock, flags); - list_for_each_entry(drv, &drivers, list) { - gig_dbg(DEBUG_DRIVER, "driver %p", drv); - spin_lock(&drv->lock); - for (i = 0; i < drv->minors; ++i) { - gig_dbg(DEBUG_DRIVER, " index %u", i); - cs = drv->cs + i; - gig_dbg(DEBUG_DRIVER, " cardstate %p", cs); - gig_dbg(DEBUG_DRIVER, " flags 0x%02x", cs->flags); - gig_dbg(DEBUG_DRIVER, " minor_index %u", - cs->minor_index); - gig_dbg(DEBUG_DRIVER, " driver %p", cs->driver); - gig_dbg(DEBUG_DRIVER, " i4l id %d", cs->myid); - } - spin_unlock(&drv->lock); - } - spin_unlock_irqrestore(&driver_lock, flags); -} - static struct cardstate *gigaset_get_cs_by_minor(unsigned minor) { unsigned long flags; diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index a69512f..6dd3607 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -70,7 +70,6 @@ enum debuglevel { 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_CHANNEL = 0x01000, /* channel allocation/deallocation */ DEBUG_TRANSCMD = 0x02000, /* AT-COMMANDS+RESPONSES */ @@ -727,7 +726,7 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, /* Deallocate driver structure. */ void gigaset_freedriver(struct gigaset_driver *drv); -void gigaset_debugdrivers(void); + struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty); struct cardstate *gigaset_get_cs_by_id(int id); void gigaset_blockdriver(struct gigaset_driver *drv); diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c index 34bca37..9bec8b9 100644 --- a/drivers/isdn/gigaset/i4l.c +++ b/drivers/isdn/gigaset/i4l.c @@ -201,8 +201,6 @@ static int command_from_LL(isdn_ctrl *cntrl) int i; size_t l; - gigaset_debugdrivers(); - gig_dbg(DEBUG_CMD, "driver: %d, command: %d, arg: 0x%lx", cntrl->driver, cntrl->command, cntrl->arg); diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index 2dfd346..f39ccdf 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c @@ -842,13 +842,14 @@ static inline void trans_receive(unsigned char *src, unsigned count, if (unlikely(bcs->ignore)) { bcs->ignore--; - hdlc_flush(bcs); return; } skb = bcs->rx_skb; - if (skb == NULL) + if (skb == NULL) { skb = gigaset_new_rx_skb(bcs); - bcs->hw.bas->goodbytes += skb->len; + if (skb == NULL) + return; + } dobytes = bcs->rx_bufsize - skb->len; while (count > 0) { dst = skb_put(skb, count < dobytes ? count : dobytes); @@ -860,6 +861,7 @@ static inline void trans_receive(unsigned char *src, unsigned count, if (dobytes == 0) { dump_bytes(DEBUG_STREAM_DUMP, "rcv data", skb->data, skb->len); + bcs->hw.bas->goodbytes += skb->len; gigaset_skb_rcvd(bcs, skb); skb = gigaset_new_rx_skb(bcs); if (skb == NULL) diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index 09b1795..91f06a3 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c @@ -20,7 +20,6 @@ #include <asm/io.h> #include <asm/system.h> -#include <pcmcia/cs.h> #include <pcmcia/cistpl.h> #include <pcmcia/ciscode.h> #include <pcmcia/ds.h> @@ -39,87 +38,32 @@ MODULE_LICENSE("GPL"); /*====================================================================*/ -/* - The event() function is this driver's Card Services event handler. - It will be called by Card Services when an appropriate card status - event is received. The config() and release() entry points are - used to configure or release a socket, in response to card insertion - and ejection events. They are invoked from the skeleton event - handler. -*/ - static int avmcs_config(struct pcmcia_device *link); static void avmcs_release(struct pcmcia_device *link); - -/* - The attach() and detach() entry points are used to create and destroy - "instances" of the driver, where each instance represents everything - needed to manage one actual PCMCIA card. -*/ - static void avmcs_detach(struct pcmcia_device *p_dev); -/*====================================================================== - - avmcs_attach() creates an "instance" of the driver, allocating - local data structures for one device. The device is registered - with Card Services. - - The dev_link structure is initialized, but we don't actually - configure the card at this point -- we wait until we receive a - card insertion event. - -======================================================================*/ - static int avmcs_probe(struct pcmcia_device *p_dev) { - - /* The io structure describes IO port mapping */ - p_dev->resource[0]->end = 16; - p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; - /* General socket configuration */ - p_dev->conf.Attributes = CONF_ENABLE_IRQ; - p_dev->conf.IntType = INT_MEMORY_AND_IO; - p_dev->conf.ConfigIndex = 1; - p_dev->conf.Present = PRESENT_OPTION; + p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; + p_dev->config_index = 1; + p_dev->config_regs = PRESENT_OPTION; return avmcs_config(p_dev); } /* avmcs_attach */ -/*====================================================================== - - This deletes a driver "instance". The device is de-registered - with Card Services. If it has been released, all local data - structures are freed. Otherwise, the structures will be freed - when the device is released. - -======================================================================*/ static void avmcs_detach(struct pcmcia_device *link) { avmcs_release(link); } /* avmcs_detach */ -/*====================================================================== - - avmcs_config() is scheduled to run after a CARD_INSERTION event - is received, to configure the PCMCIA socket, and to make the - ethernet device available to the system. - -======================================================================*/ - -static int avmcs_configcheck(struct pcmcia_device *p_dev, - cistpl_cftable_entry_t *cf, - cistpl_cftable_entry_t *dflt, - unsigned int vcc, - void *priv_data) +static int avmcs_configcheck(struct pcmcia_device *p_dev, void *priv_data) { - if (cf->io.nwin <= 0) - return -ENODEV; + p_dev->resource[0]->end = 16; + p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; - p_dev->resource[0]->start = cf->io.win[0].base; - p_dev->resource[0]->end = cf->io.win[0].len; return pcmcia_request_io(p_dev); } @@ -150,7 +94,7 @@ static int avmcs_config(struct pcmcia_device *link) /* * configure the PCMCIA socket */ - i = pcmcia_request_configuration(link, &link->conf); + i = pcmcia_enable_device(link); if (i != 0) { pcmcia_disable_device(link); break; @@ -197,13 +141,6 @@ static int avmcs_config(struct pcmcia_device *link) } /* avmcs_config */ -/*====================================================================== - - After a card is removed, avmcs_release() will unregister the net - device, and release the PCMCIA configuration. If the device is - still open, this will be postponed until it is closed. - -======================================================================*/ static void avmcs_release(struct pcmcia_device *link) { @@ -222,9 +159,7 @@ MODULE_DEVICE_TABLE(pcmcia, avmcs_ids); static struct pcmcia_driver avmcs_driver = { .owner = THIS_MODULE, - .drv = { - .name = "avm_cs", - }, + .name = "avm_cs", .probe = avmcs_probe, .remove = avmcs_detach, .id_table = avmcs_ids, diff --git a/drivers/isdn/hardware/eicon/debug.c b/drivers/isdn/hardware/eicon/debug.c index 33ce89e..3626401 100644 --- a/drivers/isdn/hardware/eicon/debug.c +++ b/drivers/isdn/hardware/eicon/debug.c @@ -862,7 +862,7 @@ void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) { diva_os_spin_lock_magic_t old_irql, old_irql1; dword sec, usec, logical, serial, org_mask; int id, best_id = 0, free_id = -1; - char tmp[256]; + char tmp[128]; diva_dbg_entry_head_t* pmsg = NULL; int len; word size; diff --git a/drivers/isdn/hardware/eicon/debuglib.h b/drivers/isdn/hardware/eicon/debuglib.h index 8ea5877..02eed6b 100644 --- a/drivers/isdn/hardware/eicon/debuglib.h +++ b/drivers/isdn/hardware/eicon/debuglib.h @@ -249,7 +249,7 @@ typedef struct _DbgHandle_ } regTime ; /* timestamp for registration */ void *pIrp ; /* ptr to pending i/o request */ unsigned long dbgMask ; /* current debug mask */ - char drvName[16] ; /* ASCII name of registered driver */ + char drvName[128] ; /* ASCII name of registered driver */ char drvTag[64] ; /* revision string */ DbgEnd dbg_end ; /* function for debug closing */ DbgLog dbg_prt ; /* function for debug appending */ diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c index ed9c555..f332b60 100644 --- a/drivers/isdn/hardware/eicon/divasmain.c +++ b/drivers/isdn/hardware/eicon/divasmain.c @@ -15,7 +15,6 @@ #include <asm/uaccess.h> #include <asm/io.h> #include <linux/ioport.h> -#include <linux/workqueue.h> #include <linux/pci.h> #include <linux/interrupt.h> #include <linux/list.h> @@ -546,7 +545,6 @@ void diva_os_remove_soft_isr(diva_os_soft_isr_t * psoft_isr) void *mem; tasklet_kill(&pdpc->divas_task); - flush_scheduled_work(); mem = psoft_isr->object; psoft_isr->object = NULL; diva_os_free(0, mem); diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index 94263c2..ac4dd78 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c @@ -20,7 +20,6 @@ #include <asm/io.h> #include <asm/system.h> -#include <pcmcia/cs.h> #include <pcmcia/cistpl.h> #include <pcmcia/ds.h> #include "hisax_cfg.h" @@ -40,67 +39,22 @@ module_param(isdnprot, int, 0); /*====================================================================*/ -/* - The event() function is this driver's Card Services event handler. - It will be called by Card Services when an appropriate card status - event is received. The config() and release() entry points are - used to configure or release a socket, in response to card insertion - and ejection events. They are invoked from the skeleton event - handler. -*/ - static int avma1cs_config(struct pcmcia_device *link) __devinit ; static void avma1cs_release(struct pcmcia_device *link); - -/* - The attach() and detach() entry points are used to create and destroy - "instances" of the driver, where each instance represents everything - needed to manage one actual PCMCIA card. -*/ - static void avma1cs_detach(struct pcmcia_device *p_dev) __devexit ; - -/*====================================================================== - - avma1cs_attach() creates an "instance" of the driver, allocating - local data structures for one device. The device is registered - with Card Services. - - The dev_link structure is initialized, but we don't actually - configure the card at this point -- we wait until we receive a - card insertion event. - -======================================================================*/ - static int __devinit avma1cs_probe(struct pcmcia_device *p_dev) { dev_dbg(&p_dev->dev, "avma1cs_attach()\n"); - /* The io structure describes IO port mapping */ - p_dev->resource[0]->end = 16; - p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; - p_dev->resource[1]->end = 16; - p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_16; - /* General socket configuration */ - p_dev->conf.Attributes = CONF_ENABLE_IRQ; - p_dev->conf.IntType = INT_MEMORY_AND_IO; - p_dev->conf.ConfigIndex = 1; - p_dev->conf.Present = PRESENT_OPTION; + p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; + p_dev->config_index = 1; + p_dev->config_regs = PRESENT_OPTION; return avma1cs_config(p_dev); } /* avma1cs_attach */ -/*====================================================================== - - This deletes a driver "instance". The device is de-registered - with Card Services. If it has been released, all local data - structures are freed. Otherwise, the structures will be freed - when the device is released. - -======================================================================*/ - static void __devexit avma1cs_detach(struct pcmcia_device *link) { dev_dbg(&link->dev, "avma1cs_detach(0x%p)\n", link); @@ -108,26 +62,13 @@ static void __devexit avma1cs_detach(struct pcmcia_device *link) kfree(link->priv); } /* avma1cs_detach */ -/*====================================================================== - - avma1cs_config() is scheduled to run after a CARD_INSERTION event - is received, to configure the PCMCIA socket, and to make the - ethernet device available to the system. - -======================================================================*/ - -static int avma1cs_configcheck(struct pcmcia_device *p_dev, - cistpl_cftable_entry_t *cf, - cistpl_cftable_entry_t *dflt, - unsigned int vcc, - void *priv_data) +static int avma1cs_configcheck(struct pcmcia_device *p_dev, void *priv_data) { - if (cf->io.nwin <= 0) - return -ENODEV; - - p_dev->resource[0]->start = cf->io.win[0].base; - p_dev->resource[0]->end = cf->io.win[0].len; + p_dev->resource[0]->end = 16; + p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; p_dev->io_lines = 5; + return pcmcia_request_io(p_dev); } @@ -161,7 +102,7 @@ static int __devinit avma1cs_config(struct pcmcia_device *link) /* * configure the PCMCIA socket */ - i = pcmcia_request_configuration(link, &link->conf); + i = pcmcia_enable_device(link); if (i != 0) { pcmcia_disable_device(link); break; @@ -175,9 +116,6 @@ static int __devinit avma1cs_config(struct pcmcia_device *link) return -ENODEV; } - printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n", - (unsigned int) link->resource[0]->start, link->irq); - icard.para[0] = link->irq; icard.para[1] = link->resource[0]->start; icard.protocol = isdnprot; @@ -196,14 +134,6 @@ static int __devinit avma1cs_config(struct pcmcia_device *link) return 0; } /* avma1cs_config */ -/*====================================================================== - - After a card is removed, avma1cs_release() will unregister the net - device, and release the PCMCIA configuration. If the device is - still open, this will be postponed until it is closed. - -======================================================================*/ - static void avma1cs_release(struct pcmcia_device *link) { unsigned long minor = (unsigned long) link->priv; @@ -216,7 +146,6 @@ static void avma1cs_release(struct pcmcia_device *link) pcmcia_disable_device(link); } /* avma1cs_release */ - static struct pcmcia_device_id avma1cs_ids[] = { PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb), PCMCIA_DEVICE_PROD_ID12("ISDN", "CARD", 0x8d9761c8, 0x01c5aa7b), @@ -226,19 +155,15 @@ MODULE_DEVICE_TABLE(pcmcia, avma1cs_ids); static struct pcmcia_driver avma1cs_driver = { .owner = THIS_MODULE, - .drv = { - .name = "avma1_cs", - }, + .name = "avma1_cs", .probe = avma1cs_probe, .remove = __devexit_p(avma1cs_detach), .id_table = avma1cs_ids, }; -/*====================================================================*/ - static int __init init_avma1_cs(void) { - return(pcmcia_register_driver(&avma1cs_driver)); + return pcmcia_register_driver(&avma1cs_driver); } static void __exit exit_avma1_cs(void) diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index 6f9afcd..b133378 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -801,6 +801,16 @@ static void closecard(int cardnr) ll_unload(csta); } +static irqreturn_t card_irq(int intno, void *dev_id) +{ + struct IsdnCardState *cs = dev_id; + irqreturn_t ret = cs->irq_func(intno, cs); + + if (ret == IRQ_HANDLED) + cs->irq_cnt++; + return ret; +} + static int init_card(struct IsdnCardState *cs) { int irq_cnt, cnt = 3, ret; @@ -809,10 +819,10 @@ static int init_card(struct IsdnCardState *cs) ret = cs->cardmsg(cs, CARD_INIT, NULL); return(ret); } - irq_cnt = kstat_irqs(cs->irq); + irq_cnt = cs->irq_cnt = 0; printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ], cs->irq, irq_cnt); - if (request_irq(cs->irq, cs->irq_func, cs->irq_flags, "HiSax", cs)) { + if (request_irq(cs->irq, card_irq, cs->irq_flags, "HiSax", cs)) { printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n", cs->irq); return 1; @@ -822,8 +832,8 @@ static int init_card(struct IsdnCardState *cs) /* Timeout 10ms */ msleep(10); printk(KERN_INFO "%s: IRQ %d count %d\n", - CardType[cs->typ], cs->irq, kstat_irqs(cs->irq)); - if (kstat_irqs(cs->irq) == irq_cnt) { + CardType[cs->typ], cs->irq, cs->irq_cnt); + if (cs->irq_cnt == irq_cnt) { printk(KERN_WARNING "%s: IRQ(%d) getting no interrupts during init %d\n", CardType[cs->typ], cs->irq, 4 - cnt); diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index b3c08aa..496d477 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -46,7 +46,6 @@ #include <asm/io.h> #include <asm/system.h> -#include <pcmcia/cs.h> #include <pcmcia/cistpl.h> #include <pcmcia/cisreg.h> #include <pcmcia/ds.h> @@ -64,26 +63,8 @@ MODULE_LICENSE("Dual MPL/GPL"); static int protocol = 2; /* EURO-ISDN Default */ module_param(protocol, int, 0); -/*====================================================================*/ - -/* - The event() function is this driver's Card Services event handler. - It will be called by Card Services when an appropriate card status - event is received. The config() and release() entry points are - used to configure or release a socket, in response to card insertion - and ejection events. They are invoked from the elsa_cs event - handler. -*/ - static int elsa_cs_config(struct pcmcia_device *link) __devinit ; static void elsa_cs_release(struct pcmcia_device *link); - -/* - The attach() and detach() entry points are used to create and destroy - "instances" of the driver, where each instance represents everything - needed to manage one actual PCMCIA card. -*/ - static void elsa_cs_detach(struct pcmcia_device *p_dev) __devexit; typedef struct local_info_t { @@ -92,18 +73,6 @@ typedef struct local_info_t { int cardnr; } local_info_t; -/*====================================================================== - - elsa_cs_attach() creates an "instance" of the driver, allocatingx - local data structures for one device. The device is registered - with Card Services. - - The dev_link structure is initialized, but we don't actually - configure the card at this point -- we wait until we receive a - card insertion event. - -======================================================================*/ - static int __devinit elsa_cs_probe(struct pcmcia_device *link) { local_info_t *local; @@ -119,31 +88,9 @@ static int __devinit elsa_cs_probe(struct pcmcia_device *link) local->cardnr = -1; - /* - General socket configuration defaults can go here. In this - client, we assume very little, and rely on the CIS for almost - everything. In most clients, many details (i.e., number, sizes, - and attributes of IO windows) are fixed by the nature of the - device, and can be hard-wired here. - */ - link->resource[0]->end = 8; - link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; - - link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.IntType = INT_MEMORY_AND_IO; - return elsa_cs_config(link); } /* elsa_cs_attach */ -/*====================================================================== - - This deletes a driver "instance". The device is de-registered - with Card Services. If it has been released, all local data - structures are freed. Otherwise, the structures will be freed - when the device is released. - -======================================================================*/ - static void __devexit elsa_cs_detach(struct pcmcia_device *link) { local_info_t *info = link->priv; @@ -156,27 +103,17 @@ static void __devexit elsa_cs_detach(struct pcmcia_device *link) kfree(info); } /* elsa_cs_detach */ -/*====================================================================== - - elsa_cs_config() is scheduled to run after a CARD_INSERTION event - is received, to configure the PCMCIA socket, and to make the - device available to the system. - -======================================================================*/ - -static int elsa_cs_configcheck(struct pcmcia_device *p_dev, - cistpl_cftable_entry_t *cf, - cistpl_cftable_entry_t *dflt, - unsigned int vcc, - void *priv_data) +static int elsa_cs_configcheck(struct pcmcia_device *p_dev, void *priv_data) { int j; p_dev->io_lines = 3; + p_dev->resource[0]->end = 8; + p_dev->resource[0]->flags &= IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; - if ((cf->io.nwin > 0) && cf->io.win[0].base) { + if ((p_dev->resource[0]->end) && p_dev->resource[0]->start) { printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n"); - p_dev->resource[0]->start = cf->io.win[0].base; if (!pcmcia_request_io(p_dev)) return 0; } else { @@ -199,6 +136,8 @@ static int __devinit elsa_cs_config(struct pcmcia_device *link) dev_dbg(&link->dev, "elsa_config(0x%p)\n", link); dev = link->priv; + link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; + i = pcmcia_loop_config(link, elsa_cs_configcheck, NULL); if (i != 0) goto failed; @@ -206,21 +145,10 @@ static int __devinit elsa_cs_config(struct pcmcia_device *link) if (!link->irq) goto failed; - i = pcmcia_request_configuration(link, &link->conf); + i = pcmcia_enable_device(link); if (i != 0) goto failed; - /* Finally, report what we've done */ - dev_info(&link->dev, "index 0x%02x: ", - link->conf.ConfigIndex); - if (link->conf.Attributes & CONF_ENABLE_IRQ) - printk(", irq %d", link->irq); - if (link->resource[0]) - printk(" & %pR", link->resource[0]); - if (link->resource[1]) - printk(" & %pR", link->resource[1]); - printk("\n"); - icard.para[0] = link->irq; icard.para[1] = link->resource[0]->start; icard.protocol = protocol; @@ -240,14 +168,6 @@ failed: return -ENODEV; } /* elsa_cs_config */ -/*====================================================================== - - After a card is removed, elsa_cs_release() will unregister the net - device, and release the PCMCIA configuration. If the device is - still open, this will be postponed until it is closed. - -======================================================================*/ - static void elsa_cs_release(struct pcmcia_device *link) { local_info_t *local = link->priv; @@ -291,9 +211,7 @@ MODULE_DEVICE_TABLE(pcmcia, elsa_ids); static struct pcmcia_driver elsa_cs_driver = { .owner = THIS_MODULE, - .drv = { - .name = "elsa_cs", - }, + .name = "elsa_cs", .probe = elsa_cs_probe, .remove = __devexit_p(elsa_cs_detach), .id_table = elsa_ids, diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c index be5faf4..5aa138e 100644 --- a/drivers/isdn/hisax/hfc_sx.c +++ b/drivers/isdn/hisax/hfc_sx.c @@ -234,13 +234,14 @@ read_fifo(struct IsdnCardState *cs, u_char fifo, int trans_max) count++; if (count > trans_max) count = trans_max; /* limit length */ - if ((skb = dev_alloc_skb(count))) { - dst = skb_put(skb, count); - while (count--) + skb = dev_alloc_skb(count); + if (skb) { + dst = skb_put(skb, count); + while (count--) *dst++ = Read_hfc(cs, HFCSX_FIF_DRD); - return(skb); - } - else return(NULL); /* no memory */ + return skb; + } else + return NULL; /* no memory */ } do { diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h index 832a878..32ab392 100644 --- a/drivers/isdn/hisax/hisax.h +++ b/drivers/isdn/hisax/hisax.h @@ -959,6 +959,7 @@ struct IsdnCardState { u_long event; struct work_struct tqueue; struct timer_list dbusytimer; + unsigned int irq_cnt; #ifdef ERROR_STATISTIC int err_crc; int err_tx; diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index a024192..360204b 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -46,7 +46,6 @@ #include <asm/io.h> #include <asm/system.h> -#include <pcmcia/cs.h> #include <pcmcia/cistpl.h> #include <pcmcia/cisreg.h> #include <pcmcia/ds.h> @@ -64,26 +63,9 @@ MODULE_LICENSE("Dual MPL/GPL"); static int protocol = 2; /* EURO-ISDN Default */ module_param(protocol, int, 0); -/*====================================================================*/ - -/* - The event() function is this driver's Card Services event handler. - It will be called by Card Services when an appropriate card status - event is received. The config() and release() entry points are - used to configure or release a socket, in response to card - insertion and ejection events. They are invoked from the sedlbauer - event handler. -*/ - static int sedlbauer_config(struct pcmcia_device *link) __devinit ; static void sedlbauer_release(struct pcmcia_device *link); -/* - The attach() and detach() entry points are used to create and destroy - "instances" of the driver, where each instance represents everything - needed to manage one actual PCMCIA card. -*/ - static void sedlbauer_detach(struct pcmcia_device *p_dev) __devexit; typedef struct local_info_t { @@ -92,18 +74,6 @@ typedef struct local_info_t { int cardnr; } local_info_t; -/*====================================================================== - - sedlbauer_attach() creates an "instance" of the driver, allocating - local data structures for one device. The device is registered - with Card Services. - - The dev_link structure is initialized, but we don't actually - configure the card at this point -- we wait until we receive a - card insertion event. - -======================================================================*/ - static int __devinit sedlbauer_probe(struct pcmcia_device *link) { local_info_t *local; @@ -118,35 +88,9 @@ static int __devinit sedlbauer_probe(struct pcmcia_device *link) local->p_dev = link; link->priv = local; - /* - General socket configuration defaults can go here. In this - client, we assume very little, and rely on the CIS for almost - everything. In most clients, many details (i.e., number, sizes, - and attributes of IO windows) are fixed by the nature of the - device, and can be hard-wired here. - */ - - /* from old sedl_cs - */ - /* The io structure describes IO port mapping */ - link->resource[0]->end = 8; - link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; - - link->conf.Attributes = 0; - link->conf.IntType = INT_MEMORY_AND_IO; - return sedlbauer_config(link); } /* sedlbauer_attach */ -/*====================================================================== - - This deletes a driver "instance". The device is de-registered - with Card Services. If it has been released, all local data - structures are freed. Otherwise, the structures will be freed - when the device is released. - -======================================================================*/ - static void __devexit sedlbauer_detach(struct pcmcia_device *link) { dev_dbg(&link->dev, "sedlbauer_detach(0x%p)\n", link); @@ -158,70 +102,15 @@ static void __devexit sedlbauer_detach(struct pcmcia_device *link) kfree(link->priv); } /* sedlbauer_detach */ -/*====================================================================== - - sedlbauer_config() is scheduled to run after a CARD_INSERTION event - is received, to configure the PCMCIA socket, and to make the - device available to the system. - -======================================================================*/ -static int sedlbauer_config_check(struct pcmcia_device *p_dev, - cistpl_cftable_entry_t *cfg, - cistpl_cftable_entry_t *dflt, - unsigned int vcc, - void *priv_data) +static int sedlbauer_config_check(struct pcmcia_device *p_dev, void *priv_data) { - if (cfg->index == 0) - return -ENODEV; - - /* Does this card need audio output? */ - if (cfg->flags & CISTPL_CFTABLE_AUDIO) { - p_dev->conf.Attributes |= CONF_ENABLE_SPKR; - p_dev->conf.Status = CCSR_AUDIO_ENA; - } + if (p_dev->config_index == 0) + return -EINVAL; - /* Use power settings for Vcc and Vpp if present */ - /* Note that the CIS values need to be rescaled */ - if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { - if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000) - return -ENODEV; - } else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) { - if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM]/10000) - return -ENODEV; - } - - if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) - p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; - else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM)) - p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000; - - p_dev->conf.Attributes |= CONF_ENABLE_IRQ; - - /* IO window settings */ - p_dev->resource[0]->end = p_dev->resource[1]->end = 0; - if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; - p_dev->resource[0]->start = io->win[0].base; - p_dev->resource[0]->end = io->win[0].len; - p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; - p_dev->resource[0]->flags |= - pcmcia_io_cfg_data_width(io->flags); - if (io->nwin > 1) { - p_dev->resource[1]->flags = p_dev->resource[0]->flags; - p_dev->resource[1]->start = io->win[1].base; - p_dev->resource[1]->end = io->win[1].len; - } - /* This reserves IO space but doesn't actually enable it */ - p_dev->io_lines = 3; - if (pcmcia_request_io(p_dev) != 0) - return -ENODEV; - } - - return 0; + p_dev->io_lines = 3; + return pcmcia_request_io(p_dev); } - - static int __devinit sedlbauer_config(struct pcmcia_device *link) { int ret; @@ -229,44 +118,17 @@ static int __devinit sedlbauer_config(struct pcmcia_device *link) dev_dbg(&link->dev, "sedlbauer_config(0x%p)\n", link); - /* - In this loop, we scan the CIS for configuration table entries, - each of which describes a valid card configuration, including - voltage, IO window, memory window, and interrupt settings. - - We make no assumptions about the card to be configured: we use - just the information available in the CIS. In an ideal world, - this would work for any PCMCIA card, but it requires a complete - and accurate CIS. In practice, a driver usually "knows" most of - these things without consulting the CIS, and most client drivers - will only use the CIS to fill in implementation-defined details. - */ + link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_CHECK_VCC | + CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO | CONF_AUTO_SET_IO; + ret = pcmcia_loop_config(link, sedlbauer_config_check, NULL); 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. - */ - ret = pcmcia_request_configuration(link, &link->conf); + ret = pcmcia_enable_device(link); if (ret) goto failed; - /* Finally, report what we've done */ - dev_info(&link->dev, "index 0x%02x:", - link->conf.ConfigIndex); - if (link->conf.Vpp) - printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10); - if (link->conf.Attributes & CONF_ENABLE_IRQ) - printk(", irq %d", link->irq); - if (link->resource[0]) - printk(" & %pR", link->resource[0]); - if (link->resource[1]) - printk(" & %pR", link->resource[1]); - printk("\n"); - icard.para[0] = link->irq; icard.para[1] = link->resource[0]->start; icard.protocol = protocol; @@ -290,14 +152,6 @@ failed: } /* sedlbauer_config */ -/*====================================================================== - - After a card is removed, sedlbauer_release() will unregister the - device, and release the PCMCIA configuration. If the device is - still open, this will be postponed until it is closed. - -======================================================================*/ - static void sedlbauer_release(struct pcmcia_device *link) { local_info_t *local = link->priv; @@ -346,9 +200,7 @@ MODULE_DEVICE_TABLE(pcmcia, sedlbauer_ids); static struct pcmcia_driver sedlbauer_driver = { .owner = THIS_MODULE, - .drv = { - .name = "sedlbauer_cs", - }, + .name = "sedlbauer_cs", .probe = sedlbauer_probe, .remove = __devexit_p(sedlbauer_detach), .id_table = sedlbauer_ids, diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index 7296102..282a446 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c @@ -27,7 +27,6 @@ #include <asm/io.h> #include <asm/system.h> -#include <pcmcia/cs.h> #include <pcmcia/cistpl.h> #include <pcmcia/cisreg.h> #include <pcmcia/ds.h> @@ -45,26 +44,8 @@ MODULE_LICENSE("GPL"); static int protocol = 2; /* EURO-ISDN Default */ module_param(protocol, int, 0); -/*====================================================================*/ - -/* - The event() function is this driver's Card Services event handler. - It will be called by Card Services when an appropriate card status - event is received. The config() and release() entry points are - used to configure or release a socket, in response to card insertion - and ejection events. They are invoked from the teles_cs event - handler. -*/ - static int teles_cs_config(struct pcmcia_device *link) __devinit ; static void teles_cs_release(struct pcmcia_device *link); - -/* - The attach() and detach() entry points are used to create and destroy - "instances" of the driver, where each instance represents everything - needed to manage one actual PCMCIA card. -*/ - static void teles_detach(struct pcmcia_device *p_dev) __devexit ; typedef struct local_info_t { @@ -73,18 +54,6 @@ typedef struct local_info_t { int cardnr; } local_info_t; -/*====================================================================== - - teles_attach() creates an "instance" of the driver, allocatingx - local data structures for one device. The device is registered - with Card Services. - - The dev_link structure is initialized, but we don't actually - configure the card at this point -- we wait until we receive a - card insertion event. - -======================================================================*/ - static int __devinit teles_probe(struct pcmcia_device *link) { local_info_t *local; @@ -99,31 +68,11 @@ static int __devinit teles_probe(struct pcmcia_device *link) local->p_dev = link; link->priv = local; - /* - General socket configuration defaults can go here. In this - client, we assume very little, and rely on the CIS for almost - everything. In most clients, many details (i.e., number, sizes, - and attributes of IO windows) are fixed by the nature of the - device, and can be hard-wired here. - */ - link->resource[0]->end = 96; - link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; - - link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.IntType = INT_MEMORY_AND_IO; + link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; return teles_cs_config(link); } /* teles_attach */ -/*====================================================================== - - This deletes a driver "instance". The device is de-registered - with Card Services. If it has been released, all local data - structures are freed. Otherwise, the structures will be freed - when the device is released. - -======================================================================*/ - static void __devexit teles_detach(struct pcmcia_device *link) { local_info_t *info = link->priv; @@ -136,27 +85,17 @@ static void __devexit teles_detach(struct pcmcia_device *link) kfree(info); } /* teles_detach */ -/*====================================================================== - - teles_cs_config() is scheduled to run after a CARD_INSERTION event - is received, to configure the PCMCIA socket, and to make the - device available to the system. - -======================================================================*/ - -static int teles_cs_configcheck(struct pcmcia_device *p_dev, - cistpl_cftable_entry_t *cf, - cistpl_cftable_entry_t *dflt, - unsigned int vcc, - void *priv_data) +static int teles_cs_configcheck(struct pcmcia_device *p_dev, void *priv_data) { int j; p_dev->io_lines = 5; + p_dev->resource[0]->end = 96; + p_dev->resource[0]->flags &= IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; - if ((cf->io.nwin > 0) && cf->io.win[0].base) { + if ((p_dev->resource[0]->end) && p_dev->resource[0]->start) { printk(KERN_INFO "(teles_cs: looks like the 96 model)\n"); - p_dev->resource[0]->start = cf->io.win[0].base; if (!pcmcia_request_io(p_dev)) return 0; } else { @@ -186,21 +125,10 @@ static int __devinit teles_cs_config(struct pcmcia_device *link) if (!link->irq) goto cs_failed; - i = pcmcia_request_configuration(link, &link->conf); + i = pcmcia_enable_device(link); if (i != 0) goto cs_failed; - /* Finally, report what we've done */ - dev_info(&link->dev, "index 0x%02x:", - link->conf.ConfigIndex); - if (link->conf.Attributes & CONF_ENABLE_IRQ) - printk(", irq %d", link->irq); - if (link->resource[0]) - printk(" & %pR", link->resource[0]); - if (link->resource[1]) - printk(" & %pR", link->resource[1]); - printk("\n"); - icard.para[0] = link->irq; icard.para[1] = link->resource[0]->start; icard.protocol = protocol; @@ -222,14 +150,6 @@ cs_failed: return -ENODEV; } /* teles_cs_config */ -/*====================================================================== - - After a card is removed, teles_cs_release() will unregister the net - device, and release the PCMCIA configuration. If the device is - still open, this will be postponed until it is closed. - -======================================================================*/ - static void teles_cs_release(struct pcmcia_device *link) { local_info_t *local = link->priv; @@ -273,9 +193,7 @@ MODULE_DEVICE_TABLE(pcmcia, teles_ids); static struct pcmcia_driver teles_cs_driver = { .owner = THIS_MODULE, - .drv = { - .name = "teles_cs", - }, + .name = "teles_cs", .probe = teles_probe, .remove = __devexit_p(teles_detach), .id_table = teles_ids, diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 51dc60d..c463162 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -14,7 +14,7 @@ #include <linux/isdn.h> #include <linux/slab.h> #include <linux/delay.h> -#include <linux/smp_lock.h> +#include <linux/mutex.h> #include "isdn_common.h" #include "isdn_tty.h" #ifdef CONFIG_ISDN_AUDIO @@ -28,6 +28,7 @@ /* Prototypes */ +static DEFINE_MUTEX(modem_info_mutex); static int isdn_tty_edit_at(const char *, int, modem_info *); static void isdn_tty_check_esc(const u_char *, u_char, int, int *, u_long *); static void isdn_tty_modem_reset_regs(modem_info *, int); @@ -1354,14 +1355,14 @@ isdn_tty_tiocmget(struct tty_struct *tty, struct file *file) if (tty->flags & (1 << TTY_IO_ERROR)) return -EIO; - lock_kernel(); + mutex_lock(&modem_info_mutex); #ifdef ISDN_DEBUG_MODEM_IOCTL printk(KERN_DEBUG "ttyI%d ioctl TIOCMGET\n", info->line); #endif control = info->mcr; status = info->msr; - unlock_kernel(); + mutex_unlock(&modem_info_mutex); return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) @@ -1385,7 +1386,7 @@ isdn_tty_tiocmset(struct tty_struct *tty, struct file *file, printk(KERN_DEBUG "ttyI%d ioctl TIOCMxxx: %x %x\n", info->line, set, clear); #endif - lock_kernel(); + mutex_lock(&modem_info_mutex); if (set & TIOCM_RTS) info->mcr |= UART_MCR_RTS; if (set & TIOCM_DTR) { @@ -1407,7 +1408,7 @@ isdn_tty_tiocmset(struct tty_struct *tty, struct file *file, isdn_tty_modem_hup(info, 1); } } - unlock_kernel(); + mutex_unlock(&modem_info_mutex); return 0; } @@ -3515,7 +3516,7 @@ isdn_tty_parse_at(modem_info * info) { atemu *m = &info->emu; char *p; - char ds[40]; + char ds[ISDN_MSNLEN]; #ifdef ISDN_DEBUG_AT printk(KERN_DEBUG "AT: '%s'\n", m->mdmcmd); @@ -3594,7 +3595,7 @@ isdn_tty_parse_at(modem_info * info) break; case '3': p++; - sprintf(ds, "\r\n%d", info->emu.charge); + snprintf(ds, sizeof(ds), "\r\n%d", info->emu.charge); isdn_tty_at_cout(ds, info); break; default:; diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c index 713ef2b..76d9e67 100644 --- a/drivers/isdn/mISDN/dsp_cmx.c +++ b/drivers/isdn/mISDN/dsp_cmx.c @@ -1237,6 +1237,7 @@ dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb) if (dsp->cmx_delay) dsp->rx_W = (dsp->rx_R + dsp->cmx_delay) & CMX_BUFF_MASK; + else dsp->rx_W = (dsp->rx_R + (dsp_poll >> 1)) & CMX_BUFF_MASK; } else { diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c index 22f38e4..5b59796 100644 --- a/drivers/isdn/mISDN/l1oip_core.c +++ b/drivers/isdn/mISDN/l1oip_core.c @@ -972,7 +972,7 @@ channel_dctrl(struct dchannel *dch, struct mISDN_ctrl_req *cq) if (debug & DEBUG_L1OIP_SOCKET) printk(KERN_DEBUG "%s: got new ip address from user " "space.\n", __func__); - l1oip_socket_open(hc); + l1oip_socket_open(hc); break; case MISDN_CTRL_UNSETPEER: if (debug & DEBUG_L1OIP_SOCKET) diff --git a/drivers/isdn/mISDN/stack.c b/drivers/isdn/mISDN/stack.c index b159bd5..a5b632e6 100644 --- a/drivers/isdn/mISDN/stack.c +++ b/drivers/isdn/mISDN/stack.c @@ -18,7 +18,6 @@ #include <linux/slab.h> #include <linux/mISDNif.h> #include <linux/kthread.h> -#include <linux/smp_lock.h> #include "core.h" static u_int *debug; @@ -205,13 +204,7 @@ mISDNStackd(void *data) struct mISDNstack *st = data; int err = 0; -#ifdef CONFIG_SMP - lock_kernel(); -#endif sigfillset(¤t->blocked); -#ifdef CONFIG_SMP - unlock_kernel(); -#endif if (*debug & DEBUG_MSG_THREAD) printk(KERN_DEBUG "mISDNStackd %s started\n", dev_name(&st->dev->dev)); diff --git a/drivers/isdn/mISDN/timerdev.c b/drivers/isdn/mISDN/timerdev.c index de43c8c..859c81e 100644 --- a/drivers/isdn/mISDN/timerdev.c +++ b/drivers/isdn/mISDN/timerdev.c @@ -267,6 +267,7 @@ static const struct file_operations mISDN_fops = { .unlocked_ioctl = mISDN_ioctl, .open = mISDN_open, .release = mISDN_close, + .llseek = no_llseek, }; static struct miscdevice mISDNtimer = { diff --git a/drivers/isdn/pcbit/edss1.c b/drivers/isdn/pcbit/edss1.c index d5920ae..80c9c16 100644 --- a/drivers/isdn/pcbit/edss1.c +++ b/drivers/isdn/pcbit/edss1.c @@ -33,7 +33,7 @@ #include "callbacks.h" -char * isdn_state_table[] = { +const char * const isdn_state_table[] = { "Closed", "Call initiated", "Overlap sending", diff --git a/drivers/isdn/pcbit/edss1.h b/drivers/isdn/pcbit/edss1.h index 0b64f97..39f8346 100644 --- a/drivers/isdn/pcbit/edss1.h +++ b/drivers/isdn/pcbit/edss1.h @@ -90,7 +90,7 @@ struct fsm_timer_entry { unsigned long timeout; /* in seconds */ }; -extern char * isdn_state_table[]; +extern const char * const isdn_state_table[]; void pcbit_fsm_event(struct pcbit_dev *, struct pcbit_chan *, unsigned short event, struct callb_data *); diff --git a/drivers/isdn/sc/interrupt.c b/drivers/isdn/sc/interrupt.c index 485be8b..f0225bc 100644 --- a/drivers/isdn/sc/interrupt.c +++ b/drivers/isdn/sc/interrupt.c @@ -112,11 +112,19 @@ irqreturn_t interrupt_handler(int dummy, void *card_inst) } else if(callid>=0x0000 && callid<=0x7FFF) { + int len; + pr_debug("%s: Got Incoming Call\n", sc_adapter[card]->devicename); - strcpy(setup.phone,&(rcvmsg.msg_data.byte_array[4])); - strcpy(setup.eazmsn, - sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn); + len = strlcpy(setup.phone, &(rcvmsg.msg_data.byte_array[4]), + sizeof(setup.phone)); + if (len >= sizeof(setup.phone)) + continue; + len = strlcpy(setup.eazmsn, + sc_adapter[card]->channel[rcvmsg.phy_link_no - 1].dn, + sizeof(setup.eazmsn)); + if (len >= sizeof(setup.eazmsn)) + continue; setup.si1 = 7; setup.si2 = 0; setup.plan = 0; @@ -176,7 +184,9 @@ irqreturn_t interrupt_handler(int dummy, void *card_inst) * Handle a GetMyNumber Rsp */ if (IS_CE_MESSAGE(rcvmsg,Call,0,GetMyNumber)){ - strcpy(sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn,rcvmsg.msg_data.byte_array); + strlcpy(sc_adapter[card]->channel[rcvmsg.phy_link_no - 1].dn, + rcvmsg.msg_data.byte_array, + sizeof(rcvmsg.msg_data.byte_array)); continue; } |