aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/isdn')
-rw-r--r--drivers/isdn/act2000/act2000.h6
-rw-r--r--drivers/isdn/capi/capidrv.c17
-rw-r--r--drivers/isdn/capi/kcapi.c19
-rw-r--r--drivers/isdn/divert/isdn_divert.c6
-rw-r--r--drivers/isdn/gigaset/bas-gigaset.c400
-rw-r--r--drivers/isdn/gigaset/common.c26
-rw-r--r--drivers/isdn/gigaset/gigaset.h3
-rw-r--r--drivers/isdn/gigaset/i4l.c2
-rw-r--r--drivers/isdn/gigaset/isocdata.c8
-rw-r--r--drivers/isdn/hardware/avm/avm_cs.c83
-rw-r--r--drivers/isdn/hardware/eicon/debug.c2
-rw-r--r--drivers/isdn/hardware/eicon/debuglib.h2
-rw-r--r--drivers/isdn/hardware/eicon/divasmain.c2
-rw-r--r--drivers/isdn/hisax/avma1_cs.c97
-rw-r--r--drivers/isdn/hisax/config.c18
-rw-r--r--drivers/isdn/hisax/elsa_cs.c100
-rw-r--r--drivers/isdn/hisax/hfc_sx.c13
-rw-r--r--drivers/isdn/hisax/hisax.h1
-rw-r--r--drivers/isdn/hisax/sedlbauer_cs.c168
-rw-r--r--drivers/isdn/hisax/teles_cs.c98
-rw-r--r--drivers/isdn/i4l/isdn_audio.c2
-rw-r--r--drivers/isdn/i4l/isdn_tty.c15
-rw-r--r--drivers/isdn/mISDN/dsp_cmx.c1
-rw-r--r--drivers/isdn/mISDN/l1oip_core.c2
-rw-r--r--drivers/isdn/mISDN/stack.c7
-rw-r--r--drivers/isdn/mISDN/timerdev.c1
-rw-r--r--drivers/isdn/pcbit/edss1.c2
-rw-r--r--drivers/isdn/pcbit/edss1.h2
-rw-r--r--drivers/isdn/sc/interrupt.c18
29 files changed, 386 insertions, 735 deletions
diff --git a/drivers/isdn/act2000/act2000.h b/drivers/isdn/act2000/act2000.h
index d4c50512a1ff..88c9423500d8 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 2978bdaa6b88..e54e79d4e2c1 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 b054494df846..3acf94cc5acd 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 70cf6bac7a5a..48e6d220f62c 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 707d9c94cf9e..178942a2ee61 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 3ca561eccd9f..db621db67f61 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 a69512fb1195..6dd360734cfd 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 34bca37d65b9..9bec8b969964 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 2dfd346fc889..f39ccdf87a17 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 09b1795516f4..91f06a3ef002 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 33ce89eed65b..362640120886 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 8ea587783e14..02eed6b4354c 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 ed9c55506797..f332b60eff6b 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 94263c22b874..ac4dd7857cbd 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 6f9afcd5ca4e..b133378d4dc9 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 b3c08aaf41c4..496d477af0f8 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 be5faf4aa868..5aa138eb0b3c 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 832a87855ffb..32ab3924aa73 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 a024192b672a..360204bc2777 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 7296102ca255..282a4467ef19 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_audio.c b/drivers/isdn/i4l/isdn_audio.c
index 861bdf3421f2..d5013935ac62 100644
--- a/drivers/isdn/i4l/isdn_audio.c
+++ b/drivers/isdn/i4l/isdn_audio.c
@@ -439,7 +439,7 @@ isdn_audio_xlaw2adpcm(adpcm_state * s, int fmt, unsigned char *in,
/*
* Goertzel algorithm.
- * See http://ptolemy.eecs.berkeley.edu/~pino/Ptolemy/papers/96/dtmf_ict/
+ * See http://ptolemy.eecs.berkeley.edu/papers/96/dtmf_ict/
* for more info.
* Result is stored into an sk_buff and queued up for later
* evaluation.
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index 51dc60da333b..c463162843ba 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 713ef2b805a2..76d9e673b4e1 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 22f38e48ac4e..5b59796ed250 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 b159bd59e64e..a5b632e67552 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(&current->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 de43c8c70ad0..859c81e9483b 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 d5920ae22d73..80c9c16fd5ef 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 0b64f97015d8..39f8346e28c5 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 485be8b1e1b3..f0225bc0f267 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;
}