summaryrefslogtreecommitdiffstats
path: root/drivers/isdn
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-10-25 17:30:53 +0100
committerIngo Molnar <mingo@elte.hu>2009-10-25 17:30:53 +0100
commit0b9e31e9264f1bad89856afb96da1688292f13b4 (patch)
tree7a9e9b6456dce993efeed8734de0a15a1f16ae94 /drivers/isdn
parentcf82ff7ea7695b0e82ba07bc5e9f1bd03a74e1aa (diff)
parent964fe080d94db82a3268443e9b9ece4c60246414 (diff)
Merge branch 'linus' into sched/core
Conflicts: fs/proc/array.c Merge reason: resolve conflict and queue up dependent patch. Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'drivers/isdn')
-rw-r--r--drivers/isdn/capi/capi.c2
-rw-r--r--drivers/isdn/capi/capidrv.c27
-rw-r--r--drivers/isdn/capi/capifs.c2
-rw-r--r--drivers/isdn/capi/capiutil.c2
-rw-r--r--drivers/isdn/capi/kcapi.c1
-rw-r--r--drivers/isdn/capi/kcapi_proc.c10
-rw-r--r--drivers/isdn/divert/divert_procfs.c1
-rw-r--r--drivers/isdn/gigaset/asyncdata.c28
-rw-r--r--drivers/isdn/gigaset/bas-gigaset.c87
-rw-r--r--drivers/isdn/gigaset/common.c134
-rw-r--r--drivers/isdn/gigaset/ev-layer.c30
-rw-r--r--drivers/isdn/gigaset/i4l.c23
-rw-r--r--drivers/isdn/gigaset/interface.c28
-rw-r--r--drivers/isdn/gigaset/isocdata.c30
-rw-r--r--drivers/isdn/hardware/mISDN/Kconfig1
-rw-r--r--drivers/isdn/hisax/arcofi.c1
-rw-r--r--drivers/isdn/hisax/hfc_2bds0.c1
-rw-r--r--drivers/isdn/hisax/hfc_pci.c1
-rw-r--r--drivers/isdn/hysdn/hysdn_procconf.c1
-rw-r--r--drivers/isdn/hysdn/hysdn_proclog.c1
-rw-r--r--drivers/isdn/i4l/Kconfig3
-rw-r--r--drivers/isdn/i4l/isdn_common.c4
-rw-r--r--drivers/isdn/mISDN/socket.c2
-rw-r--r--drivers/isdn/pcbit/drv.c1
-rw-r--r--drivers/isdn/pcbit/layer2.c1
-rw-r--r--drivers/isdn/sc/init.c1
26 files changed, 294 insertions, 129 deletions
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 2d8352419c0..65bf91e16a4 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -603,7 +603,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_CONF) {
u16 info = CAPIMSG_U16(skb->data, 12); // Info field
- if (info == 0) {
+ if ((info & 0xff00) == 0) {
mutex_lock(&cdev->ncci_list_mtx);
capincci_alloc(cdev, CAPIMSG_NCCI(skb->data));
mutex_unlock(&cdev->ncci_list_mtx);
diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c
index 650120261ab..3e6d17f42a9 100644
--- a/drivers/isdn/capi/capidrv.c
+++ b/drivers/isdn/capi/capidrv.c
@@ -40,7 +40,7 @@ static int debugmode = 0;
MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
-module_param(debugmode, uint, 0);
+module_param(debugmode, uint, S_IRUGO|S_IWUSR);
/* -------- type definitions ----------------------------------------- */
@@ -671,8 +671,8 @@ static void n0(capidrv_contr * card, capidrv_ncci * ncci)
NULL, /* Useruserdata */ /* $$$$ */
NULL /* Facilitydataarray */
);
- send_message(card, &cmsg);
plci_change_state(card, ncci->plcip, EV_PLCI_DISCONNECT_REQ);
+ send_message(card, &cmsg);
cmd.command = ISDN_STAT_BHUP;
cmd.driver = card->myid;
@@ -924,8 +924,8 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg)
*/
capi_cmsg_answer(cmsg);
cmsg->Reject = 1; /* ignore */
- send_message(card, cmsg);
plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
+ send_message(card, cmsg);
printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s ignored\n",
card->contrnr,
cmd.parm.setup.phone,
@@ -974,8 +974,8 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg)
case 2: /* Call will be rejected. */
capi_cmsg_answer(cmsg);
cmsg->Reject = 2; /* reject call, normal call clearing */
- send_message(card, cmsg);
plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
+ send_message(card, cmsg);
break;
default:
@@ -983,8 +983,8 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg)
capi_cmsg_answer(cmsg);
cmsg->Reject = 8; /* reject call,
destination out of order */
- send_message(card, cmsg);
plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
+ send_message(card, cmsg);
break;
}
return;
@@ -1020,8 +1020,8 @@ static void handle_plci(_cmsg * cmsg)
card->bchans[plcip->chan].disconnecting = 1;
plci_change_state(card, plcip, EV_PLCI_DISCONNECT_IND);
capi_cmsg_answer(cmsg);
- send_message(card, cmsg);
plci_change_state(card, plcip, EV_PLCI_DISCONNECT_RESP);
+ send_message(card, cmsg);
break;
case CAPI_DISCONNECT_CONF: /* plci */
@@ -1078,8 +1078,8 @@ static void handle_plci(_cmsg * cmsg)
if (card->bchans[plcip->chan].incoming) {
capi_cmsg_answer(cmsg);
- send_message(card, cmsg);
plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND);
+ send_message(card, cmsg);
} else {
capidrv_ncci *nccip;
capi_cmsg_answer(cmsg);
@@ -1098,13 +1098,14 @@ static void handle_plci(_cmsg * cmsg)
NULL /* NCPI */
);
nccip->msgid = cmsg->Messagenumber;
+ plci_change_state(card, plcip,
+ EV_PLCI_CONNECT_ACTIVE_IND);
+ ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_REQ);
send_message(card, cmsg);
cmd.command = ISDN_STAT_DCONN;
cmd.driver = card->myid;
cmd.arg = plcip->chan;
card->interface.statcallb(&cmd);
- plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND);
- ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_REQ);
}
break;
@@ -1193,8 +1194,8 @@ static void handle_ncci(_cmsg * cmsg)
goto notfound;
capi_cmsg_answer(cmsg);
- send_message(card, cmsg);
ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_ACTIVE_IND);
+ send_message(card, cmsg);
cmd.command = ISDN_STAT_BCONN;
cmd.driver = card->myid;
@@ -1222,8 +1223,8 @@ static void handle_ncci(_cmsg * cmsg)
0, /* Reject */
NULL /* NCPI */
);
- send_message(card, cmsg);
ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_RESP);
+ send_message(card, cmsg);
break;
}
printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n", card->contrnr);
@@ -1299,8 +1300,8 @@ static void handle_ncci(_cmsg * cmsg)
card->bchans[nccip->chan].disconnecting = 1;
ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_IND);
capi_cmsg_answer(cmsg);
- send_message(card, cmsg);
ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_RESP);
+ send_message(card, cmsg);
break;
case CAPI_DISCONNECT_B3_CONF: /* ncci */
@@ -2014,8 +2015,8 @@ static void send_listen(capidrv_contr *card)
card->cipmask,
card->cipmask2,
NULL, NULL);
- send_message(card, &cmdcmsg);
listen_change_state(card, EV_LISTEN_REQ);
+ send_message(card, &cmdcmsg);
}
static void listentimerfunc(unsigned long x)
diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c
index bff72d81f26..9f8f67b6c07 100644
--- a/drivers/isdn/capi/capifs.c
+++ b/drivers/isdn/capi/capifs.c
@@ -89,7 +89,7 @@ static int capifs_remount(struct super_block *s, int *flags, char *data)
return 0;
}
-static struct super_operations capifs_sops =
+static const struct super_operations capifs_sops =
{
.statfs = simple_statfs,
.remount_fs = capifs_remount,
diff --git a/drivers/isdn/capi/capiutil.c b/drivers/isdn/capi/capiutil.c
index 16f2e465e5f..26626eead82 100644
--- a/drivers/isdn/capi/capiutil.c
+++ b/drivers/isdn/capi/capiutil.c
@@ -1019,7 +1019,7 @@ int __init cdebug_init(void)
if (!g_debbuf->buf) {
kfree(g_cmsg);
kfree(g_debbuf);
- return -ENOMEM;;
+ return -ENOMEM;
}
g_debbuf->size = CDEBUG_GSIZE;
g_debbuf->buf[0] = 0;
diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c
index 57d26360f64..dc506ab99ca 100644
--- a/drivers/isdn/capi/kcapi.c
+++ b/drivers/isdn/capi/kcapi.c
@@ -18,6 +18,7 @@
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/proc_fs.h>
+#include <linux/sched.h>
#include <linux/seq_file.h>
#include <linux/skbuff.h>
#include <linux/workqueue.h>
diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c
index 50ed778f63f..09d4db764d2 100644
--- a/drivers/isdn/capi/kcapi_proc.c
+++ b/drivers/isdn/capi/kcapi_proc.c
@@ -89,14 +89,14 @@ static int contrstats_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations seq_controller_ops = {
+static const struct seq_operations seq_controller_ops = {
.start = controller_start,
.next = controller_next,
.stop = controller_stop,
.show = controller_show,
};
-static struct seq_operations seq_contrstats_ops = {
+static const struct seq_operations seq_contrstats_ops = {
.start = controller_start,
.next = controller_next,
.stop = controller_stop,
@@ -194,14 +194,14 @@ applstats_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations seq_applications_ops = {
+static const struct seq_operations seq_applications_ops = {
.start = applications_start,
.next = applications_next,
.stop = applications_stop,
.show = applications_show,
};
-static struct seq_operations seq_applstats_ops = {
+static const struct seq_operations seq_applstats_ops = {
.start = applications_start,
.next = applications_next,
.stop = applications_stop,
@@ -264,7 +264,7 @@ static int capi_driver_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations seq_capi_driver_ops = {
+static const struct seq_operations seq_capi_driver_ops = {
.start = capi_driver_start,
.next = capi_driver_next,
.stop = capi_driver_stop,
diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c
index 8b256a617c8..3697c409bec 100644
--- a/drivers/isdn/divert/divert_procfs.c
+++ b/drivers/isdn/divert/divert_procfs.c
@@ -16,6 +16,7 @@
#else
#include <linux/fs.h>
#endif
+#include <linux/sched.h>
#include <linux/isdnif.h>
#include <net/net_namespace.h>
#include "isdn_divert.h"
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c
index 234cc5d5331..44a58e6f8f6 100644
--- a/drivers/isdn/gigaset/asyncdata.c
+++ b/drivers/isdn/gigaset/asyncdata.c
@@ -334,7 +334,14 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
return startbytes - numbytes;
}
-/* process a block of data received from the device
+/**
+ * gigaset_m10x_input() - process a block of data received from the device
+ * @inbuf: received data and device descriptor structure.
+ *
+ * Called by hardware module {ser,usb}_gigaset with a block of received
+ * bytes. Separates the bytes received over the serial data channel into
+ * user data and command replies (locked/unlocked) according to the
+ * current state of the interface.
*/
void gigaset_m10x_input(struct inbuf_t *inbuf)
{
@@ -543,16 +550,17 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail)
return iraw_skb;
}
-/* gigaset_send_skb
- * called by common.c to queue an skb for sending
- * and start transmission if necessary
- * parameters:
- * B Channel control structure
- * skb
+/**
+ * gigaset_m10x_send_skb() - queue an skb for sending
+ * @bcs: B channel descriptor structure.
+ * @skb: data to send.
+ *
+ * Called by i4l.c to encode and queue an skb for sending, and start
+ * transmission if necessary.
+ *
* Return value:
- * number of bytes accepted for sending
- * (skb->len if ok, 0 if out of buffer space)
- * or error code (< 0, eg. -EINVAL)
+ * number of bytes accepted for sending (skb->len) if ok,
+ * error code < 0 (eg. -ENOMEM) on error
*/
int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
{
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index 781c4041f7b..5ed1d99eb9f 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -134,6 +134,7 @@ struct bas_cardstate {
#define BS_ATRDPEND 0x040 /* urb_cmd_in in use */
#define BS_ATWRPEND 0x080 /* urb_cmd_out in use */
#define BS_SUSPEND 0x100 /* USB port suspended */
+#define BS_RESETTING 0x200 /* waiting for HD_RESET_INTERRUPT_PIPE_ACK */
static struct gigaset_driver *driver = NULL;
@@ -319,6 +320,21 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
return -EINVAL;
}
+/* set/clear bits in base connection state, return previous state
+ */
+static inline int update_basstate(struct bas_cardstate *ucs,
+ int set, int clear)
+{
+ unsigned long flags;
+ int state;
+
+ spin_lock_irqsave(&ucs->lock, flags);
+ state = ucs->basstate;
+ ucs->basstate = (state & ~clear) | set;
+ spin_unlock_irqrestore(&ucs->lock, flags);
+ return state;
+}
+
/* error_hangup
* hang up any existing connection because of an unrecoverable error
* This function may be called from any context and takes care of scheduling
@@ -350,12 +366,9 @@ static inline void error_hangup(struct bc_state *bcs)
*/
static inline void error_reset(struct cardstate *cs)
{
- /* close AT command channel to recover (ignore errors) */
- req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT);
-
- //FIXME try to recover without bothering the user
- dev_err(cs->dev,
- "unrecoverable error - please disconnect Gigaset base to reset\n");
+ /* 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);
}
/* check_pending
@@ -398,8 +411,13 @@ static void check_pending(struct bas_cardstate *ucs)
case HD_DEVICE_INIT_ACK: /* no reply expected */
ucs->pending = 0;
break;
- /* HD_READ_ATMESSAGE, HD_WRITE_ATMESSAGE, HD_RESET_INTERRUPTPIPE
- * are handled separately and should never end up here
+ case HD_RESET_INTERRUPT_PIPE:
+ if (!(ucs->basstate & BS_RESETTING))
+ ucs->pending = 0;
+ break;
+ /*
+ * HD_READ_ATMESSAGE and HD_WRITE_ATMESSAGE are handled separately
+ * and should never end up here
*/
default:
dev_warn(&ucs->interface->dev,
@@ -449,21 +467,6 @@ static void cmd_in_timeout(unsigned long data)
error_reset(cs);
}
-/* set/clear bits in base connection state, return previous state
- */
-inline static int update_basstate(struct bas_cardstate *ucs,
- int set, int clear)
-{
- unsigned long flags;
- int state;
-
- spin_lock_irqsave(&ucs->lock, flags);
- state = ucs->basstate;
- ucs->basstate = (state & ~clear) | set;
- spin_unlock_irqrestore(&ucs->lock, flags);
- return state;
-}
-
/* read_ctrl_callback
* USB completion handler for control pipe input
* called by the USB subsystem in interrupt context
@@ -762,7 +765,8 @@ static void read_int_callback(struct urb *urb)
break;
case HD_RESET_INTERRUPT_PIPE_ACK:
- gig_dbg(DEBUG_USBREQ, "HD_RESET_INTERRUPT_PIPE_ACK");
+ update_basstate(ucs, 0, BS_RESETTING);
+ dev_notice(cs->dev, "interrupt pipe reset\n");
break;
case HD_SUSPEND_END:
@@ -1331,28 +1335,24 @@ 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++) {
- if (unlikely(urb->iso_frame_desc[frame].status)) {
+ numbytes = urb->iso_frame_desc[frame].actual_length;
+ if (unlikely(urb->iso_frame_desc[frame].status))
dev_warn(cs->dev,
- "isochronous read: frame %d: %s\n",
- frame,
+ "isochronous read: frame %d[%d]: %s\n",
+ frame, numbytes,
get_usb_statmsg(
urb->iso_frame_desc[frame].status));
- break;
- }
- numbytes = urb->iso_frame_desc[frame].actual_length;
- if (unlikely(numbytes > BAS_MAXFRAME)) {
+ if (unlikely(numbytes > BAS_MAXFRAME))
dev_warn(cs->dev,
"isochronous read: frame %d: "
"numbytes (%d) > BAS_MAXFRAME\n",
frame, numbytes);
- break;
- }
if (unlikely(numbytes > totleft)) {
dev_warn(cs->dev,
"isochronous read: frame %d: "
"numbytes (%d) > totleft (%d)\n",
frame, numbytes, totleft);
- break;
+ numbytes = totleft;
}
offset = urb->iso_frame_desc[frame].offset;
if (unlikely(offset + numbytes > BAS_INBUFSIZE)) {
@@ -1361,7 +1361,7 @@ static void read_iso_tasklet(unsigned long data)
"offset (%d) + numbytes (%d) "
"> BAS_INBUFSIZE\n",
frame, offset, numbytes);
- break;
+ numbytes = BAS_INBUFSIZE - offset;
}
gigaset_isoc_receive(rcvbuf + offset, numbytes, bcs);
totleft -= numbytes;
@@ -1433,6 +1433,7 @@ static void req_timeout(unsigned long data)
case HD_CLOSE_ATCHANNEL:
dev_err(bcs->cs->dev, "timeout closing AT channel\n");
+ error_reset(bcs->cs);
break;
case HD_CLOSE_B2CHANNEL:
@@ -1442,6 +1443,13 @@ static void req_timeout(unsigned long data)
error_reset(bcs->cs);
break;
+ case HD_RESET_INTERRUPT_PIPE:
+ /* error recovery escalation */
+ dev_err(bcs->cs->dev,
+ "reset interrupt pipe timeout, attempting USB reset\n");
+ usb_queue_reset_device(bcs->cs->hw.bas->interface);
+ break;
+
default:
dev_warn(bcs->cs->dev, "request 0x%02x timed out, clearing\n",
pending);
@@ -1934,6 +1942,15 @@ static int gigaset_write_cmd(struct cardstate *cs,
goto notqueued;
}
+ /* translate "+++" escape sequence sent as a single separate command
+ * into "close AT channel" command for error recovery
+ * The next command will reopen the AT channel automatically.
+ */
+ if (len == 3 && !memcmp(buf, "+++", 3)) {
+ rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT);
+ goto notqueued;
+ }
+
if (len > IF_WRITEBUF)
len = IF_WRITEBUF;
if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) {
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index e4141bf8b2f..33dcd8d72b7 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -22,6 +22,12 @@
#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Tilman Schmidt <tilman@imap.cc>, Stefan Eilers"
#define DRIVER_DESC "Driver for Gigaset 307x"
+#ifdef CONFIG_GIGASET_DEBUG
+#define DRIVER_DESC_DEBUG " (debug build)"
+#else
+#define DRIVER_DESC_DEBUG ""
+#endif
+
/* Module parameters */
int gigaset_debuglevel = DEBUG_DEFAULT;
EXPORT_SYMBOL_GPL(gigaset_debuglevel);
@@ -32,6 +38,17 @@ MODULE_PARM_DESC(debug, "debug level");
#define VALID_MINOR 0x01
#define VALID_ID 0x02
+/**
+ * gigaset_dbg_buffer() - dump data in ASCII and hex for debugging
+ * @level: debugging level.
+ * @msg: message prefix.
+ * @len: number of bytes to dump.
+ * @buf: data to dump.
+ *
+ * If the current debugging level includes one of the bits set in @level,
+ * @len bytes starting at @buf are logged to dmesg at KERN_DEBUG prio,
+ * prefixed by the text @msg.
+ */
void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
size_t len, const unsigned char *buf)
{
@@ -274,6 +291,20 @@ static void clear_events(struct cardstate *cs)
spin_unlock_irqrestore(&cs->ev_lock, flags);
}
+/**
+ * gigaset_add_event() - add event to device event queue
+ * @cs: device descriptor structure.
+ * @at_state: connection state structure.
+ * @type: event type.
+ * @ptr: pointer parameter for event.
+ * @parameter: integer parameter for event.
+ * @arg: pointer parameter for event.
+ *
+ * Allocate an event queue entry from the device's event queue, and set it up
+ * with the parameters given.
+ *
+ * Return value: added event
+ */
struct event_t *gigaset_add_event(struct cardstate *cs,
struct at_state_t *at_state, int type,
void *ptr, int parameter, void *arg)
@@ -398,6 +429,15 @@ static void make_invalid(struct cardstate *cs, unsigned mask)
spin_unlock_irqrestore(&drv->lock, flags);
}
+/**
+ * gigaset_freecs() - free all associated ressources of a device
+ * @cs: device descriptor structure.
+ *
+ * Stops all tasklets and timers, unregisters the device from all
+ * subsystems it was registered to, deallocates the device structure
+ * @cs and all structures referenced from it.
+ * Operations on the device should be stopped before calling this.
+ */
void gigaset_freecs(struct cardstate *cs)
{
int i;
@@ -506,7 +546,12 @@ static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs,
inbuf->inputstate = inputstate;
}
-/* append received bytes to inbuf */
+/**
+ * gigaset_fill_inbuf() - append received data to input buffer
+ * @inbuf: buffer structure.
+ * @src: received data.
+ * @numbytes: number of bytes received.
+ */
int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
unsigned numbytes)
{
@@ -606,20 +651,22 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
return NULL;
}
-/* gigaset_initcs
+/**
+ * gigaset_initcs() - initialize device structure
+ * @drv: hardware driver the device belongs to
+ * @channels: number of B channels supported by device
+ * @onechannel: !=0 if B channel data and AT commands share one
+ * communication channel (M10x),
+ * ==0 if B channels have separate communication channels (base)
+ * @ignoreframes: number of frames to ignore after setting up B channel
+ * @cidmode: !=0: start in CallID mode
+ * @modulename: name of driver module for LL registration
+ *
* Allocate and initialize cardstate structure for Gigaset driver
* Calls hardware dependent gigaset_initcshw() function
* Calls B channel initialization function gigaset_initbcs() for each B channel
- * parameters:
- * drv hardware driver the device belongs to
- * channels number of B channels supported by device
- * onechannel !=0: B channel data and AT commands share one
- * communication channel
- * ==0: B channels have separate communication channels
- * ignoreframes number of frames to ignore after setting up B channel
- * cidmode !=0: start in CallID mode
- * modulename name of driver module (used for I4L registration)
- * return value:
+ *
+ * Return value:
* pointer to cardstate structure
*/
struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
@@ -837,6 +884,17 @@ static void cleanup_cs(struct cardstate *cs)
}
+/**
+ * gigaset_start() - start device operations
+ * @cs: device descriptor structure.
+ *
+ * Prepares the device for use by setting up communication parameters,
+ * scheduling an EV_START event to initiate device initialization, and
+ * waiting for completion of the initialization.
+ *
+ * Return value:
+ * 1 - success, 0 - error
+ */
int gigaset_start(struct cardstate *cs)
{
unsigned long flags;
@@ -879,9 +937,15 @@ error:
}
EXPORT_SYMBOL_GPL(gigaset_start);
-/* gigaset_shutdown
- * check if a device is associated to the cardstate structure and stop it
- * return value: 0 if ok, -1 if no device was associated
+/**
+ * gigaset_shutdown() - shut down device operations
+ * @cs: device descriptor structure.
+ *
+ * Deactivates the device by scheduling an EV_SHUTDOWN event and
+ * waiting for completion of the shutdown.
+ *
+ * Return value:
+ * 0 - success, -1 - error (no device associated)
*/
int gigaset_shutdown(struct cardstate *cs)
{
@@ -912,6 +976,13 @@ exit:
}
EXPORT_SYMBOL_GPL(gigaset_shutdown);
+/**
+ * gigaset_stop() - stop device operations
+ * @cs: device descriptor structure.
+ *
+ * Stops operations on the device by scheduling an EV_STOP event and
+ * waiting for completion of the shutdown.
+ */
void gigaset_stop(struct cardstate *cs)
{
mutex_lock(&cs->mutex);
@@ -1020,6 +1091,14 @@ struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty)
return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start);
}
+/**
+ * gigaset_freedriver() - free all associated ressources of a driver
+ * @drv: driver descriptor structure.
+ *
+ * Unregisters the driver from the system and deallocates the driver
+ * structure @drv and all structures referenced from it.
+ * All devices should be shut down before calling this.
+ */
void gigaset_freedriver(struct gigaset_driver *drv)
{
unsigned long flags;
@@ -1035,14 +1114,16 @@ void gigaset_freedriver(struct gigaset_driver *drv)
}
EXPORT_SYMBOL_GPL(gigaset_freedriver);
-/* gigaset_initdriver
+/**
+ * gigaset_initdriver() - initialize driver structure
+ * @minor: First minor number
+ * @minors: Number of minors this driver can handle
+ * @procname: Name of the driver
+ * @devname: Name of the device files (prefix without minor number)
+ *
* Allocate and initialize gigaset_driver structure. Initialize interface.
- * parameters:
- * minor First minor number
- * minors Number of minors this driver can handle
- * procname Name of the driver
- * devname Name of the device files (prefix without minor number)
- * return value:
+ *
+ * Return value:
* Pointer to the gigaset_driver structure on success, NULL on failure.
*/
struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
@@ -1095,6 +1176,13 @@ error:
}
EXPORT_SYMBOL_GPL(gigaset_initdriver);
+/**
+ * gigaset_blockdriver() - block driver
+ * @drv: driver descriptor structure.
+ *
+ * Prevents the driver from attaching new devices, in preparation for
+ * deregistration.
+ */
void gigaset_blockdriver(struct gigaset_driver *drv)
{
drv->blocked = 1;
@@ -1110,7 +1198,7 @@ static int __init gigaset_init_module(void)
if (gigaset_debuglevel == 1)
gigaset_debuglevel = DEBUG_DEFAULT;
- pr_info(DRIVER_DESC "\n");
+ pr_info(DRIVER_DESC DRIVER_DESC_DEBUG "\n");
return 0;
}
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c
index 2d91049571a..cc768caa38f 100644
--- a/drivers/isdn/gigaset/ev-layer.c
+++ b/drivers/isdn/gigaset/ev-layer.c
@@ -207,7 +207,6 @@ struct reply_t gigaset_tab_nocid[] =
/* leave dle mode */
{RSP_INIT, 0, 0,SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"},
{RSP_OK, 201,201, -1, 202,-1},
- //{RSP_ZDLE, 202,202, 0, 202, 0, {ACT_ERROR}},//DELETE
{RSP_ZDLE, 202,202, 0, 0, 0, {ACT_DLE0}},
{RSP_NODEV, 200,249, -1, 0, 0, {ACT_FAKEDLE0}},
{RSP_ERROR, 200,249, -1, 0, 0, {ACT_FAILDLE0}},
@@ -265,6 +264,7 @@ struct reply_t gigaset_tab_nocid[] =
{EV_SHUTDOWN, -1, -1, -1, -1,-1, {ACT_SHUTDOWN}}, //FIXME
/* misc. */
+ {RSP_ERROR, -1, -1, -1, -1, -1, {ACT_ERROR} },
{RSP_EMPTY, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
{RSP_ZCFGT, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
{RSP_ZCFG, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
@@ -328,10 +328,9 @@ struct reply_t gigaset_tab_cid[] =
{RSP_INIT, -1, -1,SEQ_HUP, 401, 5, {0}, "+VLS=0\r"}, /* hang up */ //-1,-1?
{RSP_OK, 401,401, -1, 402, 5},
{RSP_ZVLS, 402,402, 0, 403, 5},
- {RSP_ZSAU, 403,403,ZSAU_DISCONNECT_REQ, -1,-1, {ACT_DEBUG}}, /* if not remote hup */
- //{RSP_ZSAU, 403,403,ZSAU_NULL, 401, 0, {ACT_ERROR}}, //DELETE//FIXME -> DLE0 // should we do this _before_ hanging up for base driver?
- {RSP_ZSAU, 403,403,ZSAU_NULL, 0, 0, {ACT_DISCONNECT}}, //FIXME -> DLE0 // should we do this _before_ hanging up for base driver?
- {RSP_NODEV, 401,403, -1, 0, 0, {ACT_FAKEHUP}}, //FIXME -> DLE0 // should we do this _before_ hanging up for base driver?
+ {RSP_ZSAU, 403, 403, ZSAU_DISCONNECT_REQ, -1, -1, {ACT_DEBUG} },
+ {RSP_ZSAU, 403, 403, ZSAU_NULL, 0, 0, {ACT_DISCONNECT} },
+ {RSP_NODEV, 401, 403, -1, 0, 0, {ACT_FAKEHUP} },
{RSP_ERROR, 401,401, -1, 0, 0, {ACT_ABORTHUP}},
{EV_TIMEOUT, 401,403, -1, 0, 0, {ACT_ABORTHUP}},
@@ -474,8 +473,13 @@ static int cid_of_response(char *s)
//FIXME is ;<digit>+ at end of non-CID response really impossible?
}
-/* This function will be called via task queue from the callback handler.
- * We received a modem response and have to handle it..
+/**
+ * gigaset_handle_modem_response() - process received modem response
+ * @cs: device descriptor structure.
+ *
+ * Called by asyncdata/isocdata if a block of data received from the
+ * device must be processed as a modem command response. The data is
+ * already in the cs structure.
*/
void gigaset_handle_modem_response(struct cardstate *cs)
{
@@ -707,6 +711,11 @@ static void disconnect(struct at_state_t **at_state_p)
if (bcs) {
/* B channel assigned: invoke hardware specific handler */
cs->ops->close_bchannel(bcs);
+ /* notify LL */
+ if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) {
+ bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL);
+ gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP);
+ }
} else {
/* no B channel assigned: just deallocate */
spin_lock_irqsave(&cs->lock, flags);
@@ -1429,11 +1438,12 @@ static void do_action(int action, struct cardstate *cs,
cs->gotfwver = -1;
dev_err(cs->dev, "could not read firmware version.\n");
break;
-#ifdef CONFIG_GIGASET_DEBUG
case ACT_ERROR:
- *p_genresp = 1;
- *p_resp_code = RSP_ERROR;
+ gig_dbg(DEBUG_ANY, "%s: ERROR response in ConState %d",
+ __func__, at_state->ConState);
+ cs->cur_at_seq = SEQ_NONE;
break;
+#ifdef CONFIG_GIGASET_DEBUG
case ACT_TEST:
{
static int count = 3; //2; //1;
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c
index 9b22f9cf2f3..654489d836c 100644
--- a/drivers/isdn/gigaset/i4l.c
+++ b/drivers/isdn/gigaset/i4l.c
@@ -51,6 +51,12 @@ static int writebuf_from_LL(int driverID, int channel, int ack,
return -ENODEV;
}
bcs = &cs->bcs[channel];
+
+ /* can only handle linear sk_buffs */
+ if (skb_linearize(skb) < 0) {
+ dev_err(cs->dev, "%s: skb_linearize failed\n", __func__);
+ return -ENOMEM;
+ }
len = skb->len;
gig_dbg(DEBUG_LLDATA,
@@ -79,6 +85,14 @@ static int writebuf_from_LL(int driverID, int channel, int ack,
return cs->ops->send_skb(bcs, skb);
}
+/**
+ * gigaset_skb_sent() - acknowledge sending an skb
+ * @bcs: B channel descriptor structure.
+ * @skb: sent data.
+ *
+ * Called by hardware module {bas,ser,usb}_gigaset when the data in a
+ * skb has been successfully sent, for signalling completion to the LL.
+ */
void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb)
{
unsigned len;
@@ -455,6 +469,15 @@ int gigaset_isdn_setup_accept(struct at_state_t *at_state)
return 0;
}
+/**
+ * gigaset_isdn_icall() - signal incoming call
+ * @at_state: connection state structure.
+ *
+ * Called by main module to notify the LL that an incoming call has been
+ * received. @at_state contains the parameters of the call.
+ *
+ * Return value: call disposition (ICALL_*)
+ */
int gigaset_isdn_icall(struct at_state_t *at_state)
{
struct cardstate *cs = at_state->cs;
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index 8ff7e35c706..6a8e1384e7b 100644
--- a/drivers/isdn/gigaset/interface.c
+++ b/drivers/isdn/gigaset/interface.c
@@ -408,33 +408,28 @@ static int if_write_room(struct tty_struct *tty)
return retval;
}
-/* FIXME: This function does not have error returns */
-
static int if_chars_in_buffer(struct tty_struct *tty)
{
struct cardstate *cs;
- int retval = -ENODEV;
+ int retval = 0;
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
pr_err("%s: no cardstate\n", __func__);
- return -ENODEV;
+ return 0;
}
gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
- if (mutex_lock_interruptible(&cs->mutex))
- return -ERESTARTSYS; // FIXME -EINTR?
+ mutex_lock(&cs->mutex);
- if (!cs->connected) {
+ if (!cs->connected)
gig_dbg(DEBUG_IF, "not connected");
- retval = -ENODEV;
- } else if (!cs->open_count)
+ else if (!cs->open_count)
dev_warn(cs->dev, "%s: device not opened\n", __func__);
- else if (cs->mstate != MS_LOCKED) {
+ else if (cs->mstate != MS_LOCKED)
dev_warn(cs->dev, "can't write to unlocked device\n");
- retval = -EBUSY;
- } else
+ else
retval = cs->ops->chars_in_buffer(cs);
mutex_unlock(&cs->mutex);
@@ -621,6 +616,15 @@ void gigaset_if_free(struct cardstate *cs)
tty_unregister_device(drv->tty, cs->minor_index);
}
+/**
+ * gigaset_if_receive() - pass a received block of data to the tty device
+ * @cs: device descriptor structure.
+ * @buffer: received data.
+ * @len: number of bytes received.
+ *
+ * Called by asyncdata/isocdata if a block of data received from the
+ * device must be sent to userspace through the ttyG* device.
+ */
void gigaset_if_receive(struct cardstate *cs,
unsigned char *buffer, size_t len)
{
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c
index bed38fcc432..9f3ef7b4248 100644
--- a/drivers/isdn/gigaset/isocdata.c
+++ b/drivers/isdn/gigaset/isocdata.c
@@ -429,7 +429,7 @@ static inline int hdlc_buildframe(struct isowbuf_t *iwb,
return -EAGAIN;
}
- dump_bytes(DEBUG_STREAM, "snd data", in, count);
+ dump_bytes(DEBUG_STREAM_DUMP, "snd data", in, count);
/* bitstuff and checksum input data */
fcs = PPP_INITFCS;
@@ -448,7 +448,6 @@ static inline int hdlc_buildframe(struct isowbuf_t *iwb,
/* put closing flag and repeat byte for flag idle */
isowbuf_putflag(iwb);
end = isowbuf_donewrite(iwb);
- dump_bytes(DEBUG_STREAM_DUMP, "isowbuf", iwb->data, end + 1);
return end;
}
@@ -482,6 +481,8 @@ static inline int trans_buildframe(struct isowbuf_t *iwb,
}
gig_dbg(DEBUG_STREAM, "put %d bytes", count);
+ dump_bytes(DEBUG_STREAM_DUMP, "snd data", in, count);
+
write = iwb->write;
do {
c = bitrev8(*in++);
@@ -583,7 +584,7 @@ static inline void hdlc_done(struct bc_state *bcs)
procskb->tail -= 2;
gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)",
__func__, procskb->len);
- dump_bytes(DEBUG_STREAM,
+ dump_bytes(DEBUG_STREAM_DUMP,
"rcv data", procskb->data, procskb->len);
bcs->hw.bas->goodbytes += procskb->len;
gigaset_rcv_skb(procskb, bcs->cs, bcs);
@@ -878,6 +879,8 @@ static inline void trans_receive(unsigned char *src, unsigned count,
dobytes--;
}
if (dobytes == 0) {
+ dump_bytes(DEBUG_STREAM_DUMP,
+ "rcv data", skb->data, skb->len);
gigaset_rcv_skb(skb, bcs->cs, bcs);
bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN);
if (!skb) {
@@ -973,16 +976,17 @@ void gigaset_isoc_input(struct inbuf_t *inbuf)
/* == data output ========================================================== */
-/* gigaset_send_skb
- * called by common.c to queue an skb for sending
- * and start transmission if necessary
- * parameters:
- * B Channel control structure
- * skb
- * return value:
- * number of bytes accepted for sending
- * (skb->len if ok, 0 if out of buffer space)
- * or error code (< 0, eg. -EINVAL)
+/**
+ * gigaset_isoc_send_skb() - queue an skb for sending
+ * @bcs: B channel descriptor structure.
+ * @skb: data to send.
+ *
+ * Called by i4l.c to queue an skb for sending, and start transmission if
+ * necessary.
+ *
+ * Return value:
+ * number of bytes accepted for sending (skb->len) if ok,
+ * error code < 0 (eg. -ENODEV) on error
*/
int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb)
{
diff --git a/drivers/isdn/hardware/mISDN/Kconfig b/drivers/isdn/hardware/mISDN/Kconfig
index bde55d7287f..eadc1cd34a2 100644
--- a/drivers/isdn/hardware/mISDN/Kconfig
+++ b/drivers/isdn/hardware/mISDN/Kconfig
@@ -78,6 +78,7 @@ config MISDN_NETJET
depends on PCI
select MISDN_IPAC
select ISDN_HDLC
+ select ISDN_I4L
help
Enable support for Traverse Technologies NETJet PCI cards.
diff --git a/drivers/isdn/hisax/arcofi.c b/drivers/isdn/hisax/arcofi.c
index d30ce5b978c..85a8fd8dd0b 100644
--- a/drivers/isdn/hisax/arcofi.c
+++ b/drivers/isdn/hisax/arcofi.c
@@ -10,6 +10,7 @@
*
*/
+#include <linux/sched.h>
#include "hisax.h"
#include "isdnl1.h"
#include "isac.h"
diff --git a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c
index 5c46a7130e0..8d22f50760e 100644
--- a/drivers/isdn/hisax/hfc_2bds0.c
+++ b/drivers/isdn/hisax/hfc_2bds0.c
@@ -11,6 +11,7 @@
*/
#include <linux/init.h>
+#include <linux/sched.h>
#include "hisax.h"
#include "hfc_2bds0.h"
#include "isdnl1.h"
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index d110a77940a..10914731b30 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -20,6 +20,7 @@
#include "hfc_pci.h"
#include "isdnl1.h"
#include <linux/pci.h>
+#include <linux/sched.h>
#include <linux/interrupt.h>
static const char *hfcpci_revision = "$Revision: 1.48.2.4 $";
diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c
index 8f9f4912de3..90b35e1a4b7 100644
--- a/drivers/isdn/hysdn/hysdn_procconf.c
+++ b/drivers/isdn/hysdn/hysdn_procconf.c
@@ -11,6 +11,7 @@
*
*/
+#include <linux/cred.h>
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c
index 8991d2c8ee4..8bcae28c440 100644
--- a/drivers/isdn/hysdn/hysdn_proclog.c
+++ b/drivers/isdn/hysdn/hysdn_proclog.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
+#include <linux/sched.h>
#include <linux/smp_lock.h>
#include "hysdn_defs.h"
diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig
index dd744ffd240..07c4e49f9e7 100644
--- a/drivers/isdn/i4l/Kconfig
+++ b/drivers/isdn/i4l/Kconfig
@@ -141,8 +141,7 @@ endmenu
endif
config ISDN_HDLC
- tristate
- depends on HISAX_ST5481
+ tristate
select CRC_CCITT
select BITREVERSE
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 7188c59a76f..adb1e8c36b4 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -761,7 +761,7 @@ isdn_getnum(char **p)
* Be aware that this is not an atomic operation when sleep != 0, even though
* interrupts are turned off! Well, like that we are currently only called
* on behalf of a read system call on raw device files (which are documented
- * to be dangerous and for for debugging purpose only). The inode semaphore
+ * to be dangerous and for debugging purpose only). The inode semaphore
* takes care that this is not called for the same minor device number while
* we are sleeping, but access is not serialized against simultaneous read()
* from the corresponding ttyI device. Can other ugly events, like changes
@@ -873,7 +873,7 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_que
* Be aware that this is not an atomic operation when sleep != 0, even though
* interrupts are turned off! Well, like that we are currently only called
* on behalf of a read system call on raw device files (which are documented
- * to be dangerous and for for debugging purpose only). The inode semaphore
+ * to be dangerous and for debugging purpose only). The inode semaphore
* takes care that this is not called for the same minor device number while
* we are sleeping, but access is not serialized against simultaneous read()
* from the corresponding ttyI device. Can other ugly events, like changes
diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
index c36f5213745..feb0fa45b66 100644
--- a/drivers/isdn/mISDN/socket.c
+++ b/drivers/isdn/mISDN/socket.c
@@ -415,7 +415,7 @@ data_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
}
static int data_sock_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int len)
+ char __user *optval, unsigned int len)
{
struct sock *sk = sock->sk;
int err = 0, opt = 0;
diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c
index 8c66bcb953a..123c1d6c43b 100644
--- a/drivers/isdn/pcbit/drv.c
+++ b/drivers/isdn/pcbit/drv.c
@@ -23,6 +23,7 @@
#include <linux/kernel.h>
#include <linux/types.h>
+#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
diff --git a/drivers/isdn/pcbit/layer2.c b/drivers/isdn/pcbit/layer2.c
index e075e8d2fce..30f0f45e313 100644
--- a/drivers/isdn/pcbit/layer2.c
+++ b/drivers/isdn/pcbit/layer2.c
@@ -27,6 +27,7 @@
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/types.h>
+#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c
index dd0acd06750..5a0774880d5 100644
--- a/drivers/isdn/sc/init.c
+++ b/drivers/isdn/sc/init.c
@@ -8,6 +8,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
+#include <linux/sched.h>
#include "includes.h"
#include "hardware.h"
#include "card.h"