summaryrefslogtreecommitdiff
path: root/drivers/isdn
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/isdn')
-rw-r--r--drivers/isdn/capi/capi.c50
-rw-r--r--drivers/isdn/capi/capidrv.c8
-rw-r--r--drivers/isdn/gigaset/bas-gigaset.c44
-rw-r--r--drivers/isdn/gigaset/capi.c118
-rw-r--r--drivers/isdn/gigaset/common.c59
-rw-r--r--drivers/isdn/gigaset/dummyll.c2
-rw-r--r--drivers/isdn/gigaset/ev-layer.c319
-rw-r--r--drivers/isdn/gigaset/gigaset.h30
-rw-r--r--drivers/isdn/gigaset/i4l.c12
-rw-r--r--drivers/isdn/gigaset/isocdata.c12
-rw-r--r--drivers/isdn/gigaset/ser-gigaset.c21
-rw-r--r--drivers/isdn/gigaset/usb-gigaset.c19
-rw-r--r--drivers/isdn/hardware/eicon/capifunc.c6
-rw-r--r--drivers/isdn/hardware/eicon/capimain.c4
-rw-r--r--drivers/isdn/hardware/eicon/diddfunc.c8
-rw-r--r--drivers/isdn/hardware/eicon/diva_didd.c6
-rw-r--r--drivers/isdn/hardware/eicon/divamnt.c6
-rw-r--r--drivers/isdn/hardware/eicon/divasfunc.c4
-rw-r--r--drivers/isdn/hardware/eicon/divasi.c8
-rw-r--r--drivers/isdn/hardware/eicon/divasmain.c6
-rw-r--r--drivers/isdn/hardware/eicon/idifunc.c10
-rw-r--r--drivers/isdn/hardware/eicon/mntfunc.c8
-rw-r--r--drivers/isdn/hardware/eicon/platform.h3
-rw-r--r--drivers/isdn/hardware/mISDN/avmfritz.c228
-rw-r--r--drivers/isdn/hardware/mISDN/hfc_multi.h15
-rw-r--r--drivers/isdn/hardware/mISDN/hfcmulti.c706
-rw-r--r--drivers/isdn/hardware/mISDN/hfcpci.c103
-rw-r--r--drivers/isdn/hardware/mISDN/hfcsusb.c137
-rw-r--r--drivers/isdn/hardware/mISDN/mISDNipac.c145
-rw-r--r--drivers/isdn/hardware/mISDN/mISDNisar.c131
-rw-r--r--drivers/isdn/hardware/mISDN/netjet.c218
-rw-r--r--drivers/isdn/hardware/mISDN/speedfax.c5
-rw-r--r--drivers/isdn/hardware/mISDN/w6692.c140
-rw-r--r--drivers/isdn/hysdn/hysdn_proclog.c10
-rw-r--r--drivers/isdn/i4l/isdn_bsdcomp.c2
-rw-r--r--drivers/isdn/mISDN/core.c16
-rw-r--r--drivers/isdn/mISDN/dsp.h4
-rw-r--r--drivers/isdn/mISDN/dsp_cmx.c19
-rw-r--r--drivers/isdn/mISDN/dsp_core.c1
-rw-r--r--drivers/isdn/mISDN/dsp_dtmf.c19
-rw-r--r--drivers/isdn/mISDN/hwchannel.c162
-rw-r--r--drivers/isdn/mISDN/l1oip_core.c2
-rw-r--r--drivers/isdn/mISDN/layer1.c36
-rw-r--r--drivers/isdn/mISDN/layer2.c120
-rw-r--r--drivers/isdn/mISDN/tei.c72
45 files changed, 1661 insertions, 1393 deletions
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index b902794bbf07..38c4bd87b2c9 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -336,11 +336,6 @@ static inline void
capincci_alloc_minor(struct capidev *cdev, struct capincci *np) { }
static inline void capincci_free_minor(struct capincci *np) { }
-static inline unsigned int capincci_minor_opencount(struct capincci *np)
-{
- return 0;
-}
-
#endif /* !CONFIG_ISDN_CAPI_MIDDLEWARE */
static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci)
@@ -372,6 +367,7 @@ static void capincci_free(struct capidev *cdev, u32 ncci)
}
}
+#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
static struct capincci *capincci_find(struct capidev *cdev, u32 ncci)
{
struct capincci *np;
@@ -382,7 +378,6 @@ static struct capincci *capincci_find(struct capidev *cdev, u32 ncci)
return NULL;
}
-#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
/* -------- handle data queue --------------------------------------- */
static struct sk_buff *
@@ -578,8 +573,8 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
struct tty_struct *tty;
struct capiminor *mp;
u16 datahandle;
-#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
struct capincci *np;
+#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
mutex_lock(&cdev->lock);
@@ -597,6 +592,12 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
goto unlock_out;
}
+#ifndef CONFIG_ISDN_CAPI_MIDDLEWARE
+ skb_queue_tail(&cdev->recvqueue, skb);
+ wake_up_interruptible(&cdev->recvwait);
+
+#else /* CONFIG_ISDN_CAPI_MIDDLEWARE */
+
np = capincci_find(cdev, CAPIMSG_CONTROL(skb->data));
if (!np) {
printk(KERN_ERR "BUG: capi_signal: ncci not found\n");
@@ -605,12 +606,6 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
goto unlock_out;
}
-#ifndef CONFIG_ISDN_CAPI_MIDDLEWARE
- skb_queue_tail(&cdev->recvqueue, skb);
- wake_up_interruptible(&cdev->recvwait);
-
-#else /* CONFIG_ISDN_CAPI_MIDDLEWARE */
-
mp = np->minorp;
if (!mp) {
skb_queue_tail(&cdev->recvqueue, skb);
@@ -786,7 +781,6 @@ register_out:
return retval;
case CAPI_GET_VERSION:
- {
if (copy_from_user(&data.contr, argp,
sizeof(data.contr)))
return -EFAULT;
@@ -796,11 +790,9 @@ register_out:
if (copy_to_user(argp, &data.version,
sizeof(data.version)))
return -EFAULT;
- }
- return 0;
+ return 0;
case CAPI_GET_SERIAL:
- {
if (copy_from_user(&data.contr, argp,
sizeof(data.contr)))
return -EFAULT;
@@ -810,10 +802,9 @@ register_out:
if (copy_to_user(argp, data.serial,
sizeof(data.serial)))
return -EFAULT;
- }
- return 0;
+ return 0;
+
case CAPI_GET_PROFILE:
- {
if (copy_from_user(&data.contr, argp,
sizeof(data.contr)))
return -EFAULT;
@@ -837,11 +828,9 @@ register_out:
}
if (retval)
return -EFAULT;
- }
- return 0;
+ return 0;
case CAPI_GET_MANUFACTURER:
- {
if (copy_from_user(&data.contr, argp,
sizeof(data.contr)))
return -EFAULT;
@@ -853,8 +842,8 @@ register_out:
sizeof(data.manufacturer)))
return -EFAULT;
- }
- return 0;
+ return 0;
+
case CAPI_GET_ERRCODE:
data.errcode = cdev->errcode;
cdev->errcode = CAPI_NOERROR;
@@ -870,8 +859,7 @@ register_out:
return 0;
return -ENXIO;
- case CAPI_MANUFACTURER_CMD:
- {
+ case CAPI_MANUFACTURER_CMD: {
struct capi_manufacturer_cmd mcmd;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -879,8 +867,6 @@ register_out:
return -EFAULT;
return capi20_manufacturer(mcmd.cmd, mcmd.data);
}
- return 0;
-
case CAPI_SET_FLAGS:
case CAPI_CLR_FLAGS: {
unsigned userflags;
@@ -902,6 +888,11 @@ register_out:
return -EFAULT;
return 0;
+#ifndef CONFIG_ISDN_CAPI_MIDDLEWARE
+ case CAPI_NCCI_OPENCOUNT:
+ return 0;
+
+#else /* CONFIG_ISDN_CAPI_MIDDLEWARE */
case CAPI_NCCI_OPENCOUNT: {
struct capincci *nccip;
unsigned ncci;
@@ -918,7 +909,6 @@ register_out:
return count;
}
-#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
case CAPI_NCCI_GETUNIT: {
struct capincci *nccip;
struct capiminor *mp;
diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c
index 6f5016b479f8..832bc807ed20 100644
--- a/drivers/isdn/capi/capidrv.c
+++ b/drivers/isdn/capi/capidrv.c
@@ -1593,7 +1593,7 @@ static int capidrv_command(isdn_ctrl *c, capidrv_contr *card)
return capidrv_ioctl(c, card);
switch (c->command) {
- case ISDN_CMD_DIAL:{
+ case ISDN_CMD_DIAL: {
u8 calling[ISDN_MSNLEN + 3];
u8 called[ISDN_MSNLEN + 2];
@@ -2072,7 +2072,8 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp)
card->interface.writebuf_skb = if_sendbuf;
card->interface.writecmd = NULL;
card->interface.readstat = if_readstat;
- card->interface.features = ISDN_FEATURE_L2_HDLC |
+ card->interface.features =
+ ISDN_FEATURE_L2_HDLC |
ISDN_FEATURE_L2_TRANS |
ISDN_FEATURE_L3_TRANS |
ISDN_FEATURE_P_UNKNOWN |
@@ -2080,7 +2081,8 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp)
ISDN_FEATURE_L2_X75UI |
ISDN_FEATURE_L2_X75BUI;
if (profp->support1 & (1 << 2))
- card->interface.features |= ISDN_FEATURE_L2_V11096 |
+ card->interface.features |=
+ ISDN_FEATURE_L2_V11096 |
ISDN_FEATURE_L2_V11019 |
ISDN_FEATURE_L2_V11038;
if (profp->support1 & (1 << 8))
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index 17ea0177a529..527588708948 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -411,10 +411,10 @@ static void check_pending(struct bas_cardstate *ucs)
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
- */
+ /*
+ * HD_READ_ATMESSAGE and HD_WRITE_ATMESSAGE are handled separately
+ * and should never end up here
+ */
default:
dev_warn(&ucs->interface->dev,
"unknown pending request 0x%02x cleared\n",
@@ -878,8 +878,7 @@ static void read_iso_callback(struct urb *urb)
for (i = 0; i < BAS_NUMFRAMES; i++) {
ubc->isoinlost += urb->iso_frame_desc[i].actual_length;
if (unlikely(urb->iso_frame_desc[i].status != 0 &&
- urb->iso_frame_desc[i].status !=
- -EINPROGRESS))
+ urb->iso_frame_desc[i].status != -EINPROGRESS))
ubc->loststatus = urb->iso_frame_desc[i].status;
urb->iso_frame_desc[i].status = 0;
urb->iso_frame_desc[i].actual_length = 0;
@@ -2079,16 +2078,14 @@ static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6])
/* Free hardware dependent part of the B channel structure
* parameter:
* bcs B channel structure
- * return value:
- * !=0 on success
*/
-static int gigaset_freebcshw(struct bc_state *bcs)
+static void gigaset_freebcshw(struct bc_state *bcs)
{
struct bas_bc_state *ubc = bcs->hw.bas;
int i;
if (!ubc)
- return 0;
+ return;
/* kill URBs and tasklets before freeing - better safe than sorry */
ubc->running = 0;
@@ -2106,14 +2103,13 @@ static int gigaset_freebcshw(struct bc_state *bcs)
kfree(ubc->isooutbuf);
kfree(ubc);
bcs->hw.bas = NULL;
- return 1;
}
/* Initialize hardware dependent part of the B channel structure
* parameter:
* bcs B channel structure
* return value:
- * !=0 on success
+ * 0 on success, error code < 0 on failure
*/
static int gigaset_initbcshw(struct bc_state *bcs)
{
@@ -2123,7 +2119,7 @@ static int gigaset_initbcshw(struct bc_state *bcs)
bcs->hw.bas = ubc = kmalloc(sizeof(struct bas_bc_state), GFP_KERNEL);
if (!ubc) {
pr_err("out of memory\n");
- return 0;
+ return -ENOMEM;
}
ubc->running = 0;
@@ -2140,7 +2136,7 @@ static int gigaset_initbcshw(struct bc_state *bcs)
pr_err("out of memory\n");
kfree(ubc);
bcs->hw.bas = NULL;
- return 0;
+ return -ENOMEM;
}
tasklet_init(&ubc->sent_tasklet,
write_iso_tasklet, (unsigned long) bcs);
@@ -2165,7 +2161,7 @@ static int gigaset_initbcshw(struct bc_state *bcs)
ubc->stolen0s = 0;
tasklet_init(&ubc->rcvd_tasklet,
read_iso_tasklet, (unsigned long) bcs);
- return 1;
+ return 0;
}
static void gigaset_reinitbcshw(struct bc_state *bcs)
@@ -2188,6 +2184,12 @@ static void gigaset_freecshw(struct cardstate *cs)
cs->hw.bas = NULL;
}
+/* Initialize hardware dependent part of the cardstate structure
+ * parameter:
+ * cs cardstate structure
+ * return value:
+ * 0 on success, error code < 0 on failure
+ */
static int gigaset_initcshw(struct cardstate *cs)
{
struct bas_cardstate *ucs;
@@ -2195,13 +2197,13 @@ static int gigaset_initcshw(struct cardstate *cs)
cs->hw.bas = ucs = kmalloc(sizeof *ucs, GFP_KERNEL);
if (!ucs) {
pr_err("out of memory\n");
- return 0;
+ return -ENOMEM;
}
ucs->int_in_buf = kmalloc(IP_MSGSIZE, GFP_KERNEL);
if (!ucs->int_in_buf) {
kfree(ucs);
pr_err("out of memory\n");
- return 0;
+ return -ENOMEM;
}
ucs->urb_cmd_in = NULL;
@@ -2220,7 +2222,7 @@ static int gigaset_initcshw(struct cardstate *cs)
init_waitqueue_head(&ucs->waitqueue);
INIT_WORK(&ucs->int_in_wq, int_in_work);
- return 1;
+ return 0;
}
/* freeurbs
@@ -2380,18 +2382,20 @@ static int gigaset_probe(struct usb_interface *interface,
/* save address of controller structure */
usb_set_intfdata(interface, cs);
- if (!gigaset_start(cs))
+ rc = gigaset_start(cs);
+ if (rc < 0)
goto error;
return 0;
allocerr:
dev_err(cs->dev, "could not allocate URBs\n");
+ rc = -ENOMEM;
error:
freeurbs(cs);
usb_set_intfdata(interface, NULL);
gigaset_freecs(cs);
- return -ENODEV;
+ return rc;
}
/* gigaset_disconnect
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c
index 343b5c80cb7b..27e4a3e21d64 100644
--- a/drivers/isdn/gigaset/capi.c
+++ b/drivers/isdn/gigaset/capi.c
@@ -14,6 +14,7 @@
#include "gigaset.h"
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/ratelimit.h>
#include <linux/isdn/capilli.h>
#include <linux/isdn/capicmd.h>
#include <linux/isdn/capiutil.h>
@@ -108,51 +109,35 @@ static struct {
u8 *bc;
u8 *hlc;
} cip2bchlc[] = {
- [1] = { "8090A3", NULL },
- /* Speech (A-law) */
- [2] = { "8890", NULL },
- /* Unrestricted digital information */
- [3] = { "8990", NULL },
- /* Restricted digital information */
- [4] = { "9090A3", NULL },
- /* 3,1 kHz audio (A-law) */
- [5] = { "9190", NULL },
- /* 7 kHz audio */
- [6] = { "9890", NULL },
- /* Video */
- [7] = { "88C0C6E6", NULL },
- /* Packet mode */
- [8] = { "8890218F", NULL },
- /* 56 kbit/s rate adaptation */
- [9] = { "9190A5", NULL },
- /* Unrestricted digital information with tones/announcements */
- [16] = { "8090A3", "9181" },
- /* Telephony */
- [17] = { "9090A3", "9184" },
- /* Group 2/3 facsimile */
- [18] = { "8890", "91A1" },
- /* Group 4 facsimile Class 1 */
- [19] = { "8890", "91A4" },
- /* Teletex service basic and mixed mode
- and Group 4 facsimile service Classes II and III */
- [20] = { "8890", "91A8" },
- /* Teletex service basic and processable mode */
- [21] = { "8890", "91B1" },
- /* Teletex service basic mode */
- [22] = { "8890", "91B2" },
- /* International interworking for Videotex */
- [23] = { "8890", "91B5" },
- /* Telex */
- [24] = { "8890", "91B8" },
- /* Message Handling Systems in accordance with X.400 */
- [25] = { "8890", "91C1" },
- /* OSI application in accordance with X.200 */
- [26] = { "9190A5", "9181" },
- /* 7 kHz telephony */
- [27] = { "9190A5", "916001" },
- /* Video telephony, first connection */
- [28] = { "8890", "916002" },
- /* Video telephony, second connection */
+ [1] = { "8090A3", NULL }, /* Speech (A-law) */
+ [2] = { "8890", NULL }, /* Unrestricted digital information */
+ [3] = { "8990", NULL }, /* Restricted digital information */
+ [4] = { "9090A3", NULL }, /* 3,1 kHz audio (A-law) */
+ [5] = { "9190", NULL }, /* 7 kHz audio */
+ [6] = { "9890", NULL }, /* Video */
+ [7] = { "88C0C6E6", NULL }, /* Packet mode */
+ [8] = { "8890218F", NULL }, /* 56 kbit/s rate adaptation */
+ [9] = { "9190A5", NULL }, /* Unrestricted digital information
+ * with tones/announcements */
+ [16] = { "8090A3", "9181" }, /* Telephony */
+ [17] = { "9090A3", "9184" }, /* Group 2/3 facsimile */
+ [18] = { "8890", "91A1" }, /* Group 4 facsimile Class 1 */
+ [19] = { "8890", "91A4" }, /* Teletex service basic and mixed mode
+ * and Group 4 facsimile service
+ * Classes II and III */
+ [20] = { "8890", "91A8" }, /* Teletex service basic and
+ * processable mode */
+ [21] = { "8890", "91B1" }, /* Teletex service basic mode */
+ [22] = { "8890", "91B2" }, /* International interworking for
+ * Videotex */
+ [23] = { "8890", "91B5" }, /* Telex */
+ [24] = { "8890", "91B8" }, /* Message Handling Systems
+ * in accordance with X.400 */
+ [25] = { "8890", "91C1" }, /* OSI application
+ * in accordance with X.200 */
+ [26] = { "9190A5", "9181" }, /* 7 kHz telephony */
+ [27] = { "9190A5", "916001" }, /* Video telephony, first connection */
+ [28] = { "8890", "916002" }, /* Video telephony, second connection */
};
/*
@@ -223,10 +208,14 @@ get_appl(struct gigaset_capi_ctr *iif, u16 appl)
static inline void dump_cmsg(enum debuglevel level, const char *tag, _cmsg *p)
{
#ifdef CONFIG_GIGASET_DEBUG
+ /* dump at most 20 messages in 20 secs */
+ static DEFINE_RATELIMIT_STATE(msg_dump_ratelimit, 20 * HZ, 20);
_cdebbuf *cdb;
if (!(gigaset_debuglevel & level))
return;
+ if (!___ratelimit(&msg_dump_ratelimit, tag))
+ return;
cdb = capi_cmsg2str(p);
if (cdb) {
@@ -1192,7 +1181,9 @@ static void do_facility_req(struct gigaset_capi_ctr *iif,
confparam[3] = 2; /* length */
capimsg_setu16(confparam, 4, CapiSuccess);
break;
- /* ToDo: add supported services */
+
+ /* ToDo: add supported services */
+
default:
dev_notice(cs->dev,
"%s: unsupported supplementary service function 0x%04x\n",
@@ -1766,7 +1757,8 @@ static void do_connect_b3_req(struct gigaset_capi_ctr *iif,
/* NCPI parameter: not applicable for B3 Transparent */
ignore_cstruct_param(cs, cmsg->NCPI, "CONNECT_B3_REQ", "NCPI");
- send_conf(iif, ap, skb, (cmsg->NCPI && cmsg->NCPI[0]) ?
+ send_conf(iif, ap, skb,
+ (cmsg->NCPI && cmsg->NCPI[0]) ?
CapiNcpiNotSupportedByProtocol : CapiSuccess);
}
@@ -1882,6 +1874,9 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif,
/* check for active logical connection */
if (bcs->apconnstate >= APCONN_ACTIVE) {
+ /* clear it */
+ bcs->apconnstate = APCONN_SETUP;
+
/*
* emit DISCONNECT_B3_IND with cause 0x3301
* use separate cmsg structure, as the content of iif->acmsg
@@ -1906,6 +1901,7 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif,
}
capi_cmsg2message(b3cmsg,
__skb_put(b3skb, CAPI_DISCONNECT_B3_IND_BASELEN));
+ dump_cmsg(DEBUG_CMD, __func__, b3cmsg);
kfree(b3cmsg);
capi_ctr_handle_message(&iif->ctr, ap->id, b3skb);
}
@@ -1966,7 +1962,8 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif,
/* NCPI parameter: not applicable for B3 Transparent */
ignore_cstruct_param(cs, cmsg->NCPI,
"DISCONNECT_B3_REQ", "NCPI");
- send_conf(iif, ap, skb, (cmsg->NCPI && cmsg->NCPI[0]) ?
+ send_conf(iif, ap, skb,
+ (cmsg->NCPI && cmsg->NCPI[0]) ?
CapiNcpiNotSupportedByProtocol : CapiSuccess);
}
@@ -2059,12 +2056,6 @@ static void do_reset_b3_req(struct gigaset_capi_ctr *iif,
}
/*
- * dump unsupported/ignored messages at most twice per minute,
- * some apps send those very frequently
- */
-static unsigned long ignored_msg_dump_time;
-
-/*
* unsupported CAPI message handler
*/
static void do_unsupported(struct gigaset_capi_ctr *iif,
@@ -2073,8 +2064,7 @@ static void do_unsupported(struct gigaset_capi_ctr *iif,
{
/* decode message */
capi_message2cmsg(&iif->acmsg, skb->data);
- if (printk_timed_ratelimit(&ignored_msg_dump_time, 30 * 1000))
- dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
+ dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState);
}
@@ -2085,11 +2075,9 @@ static void do_nothing(struct gigaset_capi_ctr *iif,
struct gigaset_capi_appl *ap,
struct sk_buff *skb)
{
- if (printk_timed_ratelimit(&ignored_msg_dump_time, 30 * 1000)) {
- /* decode message */
- capi_message2cmsg(&iif->acmsg, skb->data);
- dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
- }
+ /* decode message */
+ capi_message2cmsg(&iif->acmsg, skb->data);
+ dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
dev_kfree_skb_any(skb);
}
@@ -2358,7 +2346,7 @@ static const struct file_operations gigaset_proc_fops = {
* @cs: device descriptor structure.
* @isdnid: device name.
*
- * Return value: 1 for success, 0 for failure
+ * Return value: 0 on success, error code < 0 on failure
*/
int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
{
@@ -2368,7 +2356,7 @@ int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
iif = kmalloc(sizeof(*iif), GFP_KERNEL);
if (!iif) {
pr_err("%s: out of memory\n", __func__);
- return 0;
+ return -ENOMEM;
}
/* prepare controller structure */
@@ -2392,12 +2380,12 @@ int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
if (rc) {
pr_err("attach_capi_ctr failed (%d)\n", rc);
kfree(iif);
- return 0;
+ return rc;
}
cs->iif = iif;
cs->hw_hdr_len = CAPI_DATA_B3_REQ_LEN;
- return 1;
+ return 0;
}
/**
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index 76792707f995..aa41485bc594 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -194,13 +194,13 @@ int gigaset_get_channel(struct bc_state *bcs)
gig_dbg(DEBUG_CHANNEL, "could not allocate channel %d",
bcs->channel);
spin_unlock_irqrestore(&bcs->cs->lock, flags);
- return 0;
+ return -EBUSY;
}
++bcs->use_count;
bcs->busy = 1;
gig_dbg(DEBUG_CHANNEL, "allocated channel %d", bcs->channel);
spin_unlock_irqrestore(&bcs->cs->lock, flags);
- return 1;
+ return 0;
}
struct bc_state *gigaset_get_free_channel(struct cardstate *cs)
@@ -258,7 +258,7 @@ int gigaset_get_channels(struct cardstate *cs)
spin_unlock_irqrestore(&cs->lock, flags);
gig_dbg(DEBUG_CHANNEL,
"could not allocate all channels");
- return 0;
+ return -EBUSY;
}
for (i = 0; i < cs->channels; ++i)
++cs->bcs[i].use_count;
@@ -266,7 +266,7 @@ int gigaset_get_channels(struct cardstate *cs)
gig_dbg(DEBUG_CHANNEL, "allocated all channels");
- return 1;
+ return 0;
}
void gigaset_free_channels(struct cardstate *cs)
@@ -362,7 +362,7 @@ struct event_t *gigaset_add_event(struct cardstate *cs,
}
EXPORT_SYMBOL_GPL(gigaset_add_event);
-static void free_strings(struct at_state_t *at_state)
+static void clear_at_state(struct at_state_t *at_state)
{
int i;
@@ -372,18 +372,13 @@ static void free_strings(struct at_state_t *at_state)
}
}
-static void clear_at_state(struct at_state_t *at_state)
-{
- free_strings(at_state);
-}
-
-static void dealloc_at_states(struct cardstate *cs)
+static void dealloc_temp_at_states(struct cardstate *cs)
{
struct at_state_t *cur, *next;
list_for_each_entry_safe(cur, next, &cs->temp_at_states, list) {
list_del(&cur->list);
- free_strings(cur);
+ clear_at_state(cur);
kfree(cur);
}
}
@@ -393,8 +388,7 @@ static void gigaset_freebcs(struct bc_state *bcs)
int i;
gig_dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel);
- if (!bcs->cs->ops->freebcshw(bcs))
- gig_dbg(DEBUG_INIT, "failed");
+ bcs->cs->ops->freebcshw(bcs);
gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel);
clear_at_state(&bcs->at_state);
@@ -512,7 +506,7 @@ void gigaset_freecs(struct cardstate *cs)
case 1: /* error when registering to LL */
gig_dbg(DEBUG_INIT, "clearing at_state");
clear_at_state(&cs->at_state);
- dealloc_at_states(cs);
+ dealloc_temp_at_states(cs);
/* fall through */
case 0: /* error in basic setup */
@@ -571,6 +565,8 @@ static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct cardstate *cs)
* @inbuf: buffer structure.
* @src: received data.
* @numbytes: number of bytes received.
+ *
+ * Return value: !=0 if some data was appended
*/
int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
unsigned numbytes)
@@ -614,8 +610,8 @@ int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
EXPORT_SYMBOL_GPL(gigaset_fill_inbuf);
/* Initialize the b-channel structure */
-static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
- struct cardstate *cs, int channel)
+static int gigaset_initbcs(struct bc_state *bcs, struct cardstate *cs,
+ int channel)
{
int i;
@@ -654,11 +650,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
bcs->apconnstate = 0;
gig_dbg(DEBUG_INIT, " setting up bcs[%d]->hw", channel);
- if (cs->ops->initbcshw(bcs))
- return bcs;
-
- gig_dbg(DEBUG_INIT, " failed");
- return NULL;
+ return cs->ops->initbcshw(bcs);
}
/**
@@ -757,7 +749,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
cs->cmdbytes = 0;
gig_dbg(DEBUG_INIT, "setting up iif");
- if (!gigaset_isdn_regdev(cs, modulename)) {
+ if (gigaset_isdn_regdev(cs, modulename) < 0) {
pr_err("error registering ISDN device\n");
goto error;
}
@@ -765,7 +757,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
make_valid(cs, VALID_ID);
++cs->cs_init;
gig_dbg(DEBUG_INIT, "setting up hw");
- if (!cs->ops->initcshw(cs))
+ if (cs->ops->initcshw(cs) < 0)
goto error;
++cs->cs_init;
@@ -779,7 +771,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
/* set up channel data structures */
for (i = 0; i < channels; ++i) {
gig_dbg(DEBUG_INIT, "setting up bcs[%d]", i);
- if (!gigaset_initbcs(cs->bcs + i, cs, i)) {
+ if (gigaset_initbcs(cs->bcs + i, cs, i) < 0) {
pr_err("could not allocate channel %d data\n", i);
goto error;
}
@@ -848,8 +840,7 @@ static void cleanup_cs(struct cardstate *cs)
cs->mstate = MS_UNINITIALIZED;
clear_at_state(&cs->at_state);
- dealloc_at_states(cs);
- free_strings(&cs->at_state);
+ dealloc_temp_at_states(cs);
gigaset_at_init(&cs->at_state, NULL, cs, 0);
cs->inbuf->inputstate = INS_command;
@@ -875,7 +866,7 @@ static void cleanup_cs(struct cardstate *cs)
for (i = 0; i < cs->channels; ++i) {
gigaset_freebcs(cs->bcs + i);
- if (!gigaset_initbcs(cs->bcs + i, cs, i))
+ if (gigaset_initbcs(cs->bcs + i, cs, i) < 0)
pr_err("could not allocate channel %d data\n", i);
}
@@ -896,14 +887,14 @@ static void cleanup_cs(struct cardstate *cs)
* waiting for completion of the initialization.
*
* Return value:
- * 1 - success, 0 - error
+ * 0 on success, error code < 0 on failure
*/
int gigaset_start(struct cardstate *cs)
{
unsigned long flags;
if (mutex_lock_interruptible(&cs->mutex))
- return 0;
+ return -EBUSY;
spin_lock_irqsave(&cs->lock, flags);
cs->connected = 1;
@@ -927,11 +918,11 @@ int gigaset_start(struct cardstate *cs)
wait_event(cs->waitqueue, !cs->waiting);
mutex_unlock(&cs->mutex);
- return 1;
+ return 0;
error:
mutex_unlock(&cs->mutex);
- return 0;
+ return -ENOMEM;
}
EXPORT_SYMBOL_GPL(gigaset_start);
@@ -943,7 +934,7 @@ EXPORT_SYMBOL_GPL(gigaset_start);
* waiting for completion of the shutdown.
*
* Return value:
- * 0 - success, -1 - error (no device associated)
+ * 0 - success, -ENODEV - error (no device associated)
*/
int gigaset_shutdown(struct cardstate *cs)
{
@@ -951,7 +942,7 @@ int gigaset_shutdown(struct cardstate *cs)
if (!(cs->flags & VALID_MINOR)) {
mutex_unlock(&cs->mutex);
- return -1;
+ return -ENODEV;
}
cs->waiting = 1;
diff --git a/drivers/isdn/gigaset/dummyll.c b/drivers/isdn/gigaset/dummyll.c
index 19b1c779d50f..570c2d53b84e 100644
--- a/drivers/isdn/gigaset/dummyll.c
+++ b/drivers/isdn/gigaset/dummyll.c
@@ -60,7 +60,7 @@ void gigaset_isdn_stop(struct cardstate *cs)
int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
{
- return 1;
+ return 0;
}
void gigaset_isdn_unregdev(struct cardstate *cs)
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c
index 624a8256a77f..2e6963dc740e 100644
--- a/drivers/isdn/gigaset/ev-layer.c
+++ b/drivers/isdn/gigaset/ev-layer.c
@@ -153,103 +153,104 @@ struct reply_t gigaset_tab_nocid[] =
* action, command */
/* initialize device, set cid mode if possible */
- {RSP_INIT, -1, -1, SEQ_INIT, 100, 1, {ACT_TIMEOUT} },
+ {RSP_INIT, -1, -1, SEQ_INIT, 100, 1, {ACT_TIMEOUT} },
- {EV_TIMEOUT, 100, 100, -1, 101, 3, {0}, "Z\r"},
- {RSP_OK, 101, 103, -1, 120, 5, {ACT_GETSTRING},
- "+GMR\r"},
+ {EV_TIMEOUT, 100, 100, -1, 101, 3, {0}, "Z\r"},
+ {RSP_OK, 101, 103, -1, 120, 5, {ACT_GETSTRING},
+ "+GMR\r"},
- {EV_TIMEOUT, 101, 101, -1, 102, 5, {0}, "Z\r"},
- {RSP_ERROR, 101, 101, -1, 102, 5, {0}, "Z\r"},
+ {EV_TIMEOUT, 101, 101, -1, 102, 5, {0}, "Z\r"},
+ {RSP_ERROR, 101, 101, -1, 102, 5, {0}, "Z\r"},
- {EV_TIMEOUT, 102, 102, -1, 108, 5, {ACT_SETDLE1},
- "^SDLE=0\r"},
- {RSP_OK, 108, 108, -1, 104, -1},
- {RSP_ZDLE, 104, 104, 0, 103, 5, {0}, "Z\r"},
- {EV_TIMEOUT, 104, 104, -1, 0, 0, {ACT_FAILINIT} },
- {RSP_ERROR, 108, 108, -1, 0, 0, {ACT_FAILINIT} },
+ {EV_TIMEOUT, 102, 102, -1, 108, 5, {ACT_SETDLE1},
+ "^SDLE=0\r"},
+ {RSP_OK, 108, 108, -1, 104, -1},
+ {RSP_ZDLE, 104, 104, 0, 103, 5, {0}, "Z\r"},
+ {EV_TIMEOUT, 104, 104, -1, 0, 0, {ACT_FAILINIT} },
+ {RSP_ERROR, 108, 108, -1, 0, 0, {ACT_FAILINIT} },
- {EV_TIMEOUT, 108, 108, -1, 105, 2, {ACT_SETDLE0,
- ACT_HUPMODEM,
- ACT_TIMEOUT} },
- {EV_TIMEOUT, 105, 105, -1, 103, 5, {0}, "Z\r"},
+ {EV_TIMEOUT, 108, 108, -1, 105, 2, {ACT_SETDLE0,
+ ACT_HUPMODEM,
+ ACT_TIMEOUT} },
+ {EV_TIMEOUT, 105, 105, -1, 103, 5, {0}, "Z\r"},
- {RSP_ERROR, 102, 102, -1, 107, 5, {0}, "^GETPRE\r"},
- {RSP_OK, 107, 107, -1, 0, 0, {ACT_CONFIGMODE} },
- {RSP_ERROR, 107, 107, -1, 0, 0, {ACT_FAILINIT} },
- {EV_TIMEOUT, 107, 107, -1, 0, 0, {ACT_FAILINIT} },
+ {RSP_ERROR, 102, 102, -1, 107, 5, {0}, "^GETPRE\r"},
+ {RSP_OK, 107, 107, -1, 0, 0, {ACT_CONFIGMODE} },
+ {RSP_ERROR, 107, 107, -1, 0, 0, {ACT_FAILINIT} },
+ {EV_TIMEOUT, 107, 107, -1, 0, 0, {ACT_FAILINIT} },
- {RSP_ERROR, 103, 103, -1, 0, 0, {ACT_FAILINIT} },
- {EV_TIMEOUT, 103, 103, -1, 0, 0, {ACT_FAILINIT} },
+ {RSP_ERROR, 103, 103, -1, 0, 0, {ACT_FAILINIT} },
+ {EV_TIMEOUT, 103, 103, -1, 0, 0, {ACT_FAILINIT} },
- {RSP_STRING, 120, 120, -1, 121, -1, {ACT_SETVER} },
+ {RSP_STRING, 120, 120, -1, 121, -1, {ACT_SETVER} },
- {EV_TIMEOUT, 120, 121, -1, 0, 0, {ACT_FAILVER,
- ACT_INIT} },
- {RSP_ERROR, 120, 121, -1, 0, 0, {ACT_FAILVER,
- ACT_INIT} },
- {RSP_OK, 121, 121, -1, 0, 0, {ACT_GOTVER,
- ACT_INIT} },
+ {EV_TIMEOUT, 120, 121, -1, 0, 0, {ACT_FAILVER,
+ ACT_INIT} },
+ {RSP_ERROR, 120, 121, -1, 0, 0, {ACT_FAILVER,
+ ACT_INIT} },
+ {RSP_OK, 121, 121, -1, 0, 0, {ACT_GOTVER,
+ ACT_INIT} },
+ {RSP_NONE, 121, 121, -1, 120, 0, {ACT_GETSTRING} },
/* leave dle mode */
- {RSP_INIT, 0, 0, SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"},
- {RSP_OK, 201, 201, -1, 202, -1},
- {RSP_ZDLE, 202, 202, 0, 0, 0, {ACT_DLE0} },
- {RSP_NODEV, 200, 249, -1, 0, 0, {ACT_FAKEDLE0} },
- {RSP_ERROR, 200, 249, -1, 0, 0, {ACT_FAILDLE0} },
- {EV_TIMEOUT, 200, 249, -1, 0, 0, {ACT_FAILDLE0} },
+ {RSP_INIT, 0, 0, SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"},
+ {RSP_OK, 201, 201, -1, 202, -1},
+ {RSP_ZDLE, 202, 202, 0, 0, 0, {ACT_DLE0} },
+ {RSP_NODEV, 200, 249, -1, 0, 0, {ACT_FAKEDLE0} },
+ {RSP_ERROR, 200, 249, -1, 0, 0, {ACT_FAILDLE0} },
+ {EV_TIMEOUT, 200, 249, -1, 0, 0, {ACT_FAILDLE0} },
/* enter dle mode */
- {RSP_INIT, 0, 0, SEQ_DLE1, 251, 5, {0}, "^SDLE=1\r"},
- {RSP_OK, 251, 251, -1, 252, -1},
- {RSP_ZDLE, 252, 252, 1, 0, 0, {ACT_DLE1} },
- {RSP_ERROR, 250, 299, -1, 0, 0, {ACT_FAILDLE1} },
- {EV_TIMEOUT, 250, 299, -1, 0, 0, {ACT_FAILDLE1} },
+ {RSP_INIT, 0, 0, SEQ_DLE1, 251, 5, {0}, "^SDLE=1\r"},
+ {RSP_OK, 251, 251, -1, 252, -1},
+ {RSP_ZDLE, 252, 252, 1, 0, 0, {ACT_DLE1} },
+ {RSP_ERROR, 250, 299, -1, 0, 0, {ACT_FAILDLE1} },
+ {EV_TIMEOUT, 250, 299, -1, 0, 0, {ACT_FAILDLE1} },
/* incoming call */
- {RSP_RING, -1, -1, -1, -1, -1, {ACT_RING} },
+ {RSP_RING, -1, -1, -1, -1, -1, {ACT_RING} },
/* get cid */
- {RSP_INIT, 0, 0, SEQ_CID, 301, 5, {0}, "^SGCI?\r"},
- {RSP_OK, 301, 301, -1, 302, -1},
- {RSP_ZGCI, 302, 302, -1, 0, 0, {ACT_CID} },
- {RSP_ERROR, 301, 349, -1, 0, 0, {ACT_FAILCID} },
- {EV_TIMEOUT, 301, 349, -1, 0, 0, {ACT_FAILCID} },
+ {RSP_INIT, 0, 0, SEQ_CID, 301, 5, {0}, "^SGCI?\r"},
+ {RSP_OK, 301, 301, -1, 302, -1},
+ {RSP_ZGCI, 302, 302, -1, 0, 0, {ACT_CID} },
+ {RSP_ERROR, 301, 349, -1, 0, 0, {ACT_FAILCID} },
+ {EV_TIMEOUT, 301, 349, -1, 0, 0, {ACT_FAILCID} },
/* enter cid mode */
- {RSP_INIT, 0, 0, SEQ_CIDMODE, 150, 5, {0}, "^SGCI=1\r"},
- {RSP_OK, 150, 150, -1, 0, 0, {ACT_CMODESET} },
- {RSP_ERROR, 150, 150, -1, 0, 0, {ACT_FAILCMODE} },
- {EV_TIMEOUT, 150, 150, -1, 0, 0, {ACT_FAILCMODE} },
+ {RSP_INIT, 0, 0, SEQ_CIDMODE, 150, 5, {0}, "^SGCI=1\r"},
+ {RSP_OK, 150, 150, -1, 0, 0, {ACT_CMODESET} },
+ {RSP_ERROR, 150, 150, -1, 0, 0, {ACT_FAILCMODE} },
+ {EV_TIMEOUT, 150, 150, -1, 0, 0, {ACT_FAILCMODE} },
/* leave cid mode */
- {RSP_INIT, 0, 0, SEQ_UMMODE, 160, 5, {0}, "Z\r"},
- {RSP_OK, 160, 160, -1, 0, 0, {ACT_UMODESET} },
- {RSP_ERROR, 160, 160, -1, 0, 0, {ACT_FAILUMODE} },
- {EV_TIMEOUT, 160, 160, -1, 0, 0, {ACT_FAILUMODE} },
+ {RSP_INIT, 0, 0, SEQ_UMMODE, 160, 5, {0}, "Z\r"},
+ {RSP_OK, 160, 160, -1, 0, 0, {ACT_UMODESET} },
+ {RSP_ERROR, 160, 160, -1, 0, 0, {ACT_FAILUMODE} },
+ {EV_TIMEOUT, 160, 160, -1, 0, 0, {ACT_FAILUMODE} },
/* abort getting cid */
- {RSP_INIT, 0, 0, SEQ_NOCID, 0, 0, {ACT_ABORTCID} },
+ {RSP_INIT, 0, 0, SEQ_NOCID, 0, 0, {ACT_ABORTCID} },
/* reset */
- {RSP_INIT, 0, 0, SEQ_SHUTDOWN, 504, 5, {0}, "Z\r"},
- {RSP_OK, 504, 504, -1, 0, 0, {ACT_SDOWN} },
- {RSP_ERROR, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} },
- {EV_TIMEOUT, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} },
- {RSP_NODEV, 501, 599, -1, 0, 0, {ACT_FAKESDOWN} },
-
- {EV_PROC_CIDMODE, -1, -1, -1, -1, -1, {ACT_PROC_CIDMODE} },
- {EV_IF_LOCK, -1, -1, -1, -1, -1, {ACT_IF_LOCK} },
- {EV_IF_VER, -1, -1, -1, -1, -1, {ACT_IF_VER} },
- {EV_START, -1, -1, -1, -1, -1, {ACT_START} },
- {EV_STOP, -1, -1, -1, -1, -1, {ACT_STOP} },
- {EV_SHUTDOWN, -1, -1, -1, -1, -1, {ACT_SHUTDOWN} },
+ {RSP_INIT, 0, 0, SEQ_SHUTDOWN, 504, 5, {0}, "Z\r"},
+ {RSP_OK, 504, 504, -1, 0, 0, {ACT_SDOWN} },
+ {RSP_ERROR, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} },
+ {EV_TIMEOUT, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} },
+ {RSP_NODEV, 501, 599, -1, 0, 0, {ACT_FAKESDOWN} },
+
+ {EV_PROC_CIDMODE, -1, -1, -1, -1, -1, {ACT_PROC_CIDMODE} },
+ {EV_IF_LOCK, -1, -1, -1, -1, -1, {ACT_IF_LOCK} },
+ {EV_IF_VER, -1, -1, -1, -1, -1, {ACT_IF_VER} },
+ {EV_START, -1, -1, -1, -1, -1, {ACT_START} },
+ {EV_STOP, -1, -1, -1, -1, -1, {ACT_STOP} },
+ {EV_SHUTDOWN, -1, -1, -1, -1, -1, {ACT_SHUTDOWN} },
/* misc. */
- {RSP_ERROR, -1, -1, -1, -1, -1, {ACT_ERROR} },
- {RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} },
- {RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} },
- {RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} },
+ {RSP_ERROR, -1, -1, -1, -1, -1, {ACT_ERROR} },
+ {RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} },
+ {RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} },
+ {RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} },
{RSP_LAST}
};
@@ -261,90 +262,90 @@ struct reply_t gigaset_tab_cid[] =
* action, command */
/* dial */
- {EV_DIAL, -1, -1, -1, -1, -1, {ACT_DIAL} },
- {RSP_INIT, 0, 0, SEQ_DIAL, 601, 5, {ACT_CMD + AT_BC} },
- {RSP_OK, 601, 601, -1, 603, 5, {ACT_CMD + AT_PROTO} },
- {RSP_OK, 603, 603, -1, 604, 5, {ACT_CMD + AT_TYPE} },
- {RSP_OK, 604, 604, -1, 605, 5, {ACT_CMD + AT_MSN} },
- {RSP_NULL, 605, 605, -1, 606, 5, {ACT_CMD + AT_CLIP} },
- {RSP_OK, 605, 605, -1, 606, 5, {ACT_CMD + AT_CLIP} },
- {RSP_NULL, 606, 606, -1, 607, 5, {ACT_CMD + AT_ISO} },
- {RSP_OK, 606, 606, -1, 607, 5, {ACT_CMD + AT_ISO} },
- {RSP_OK, 607, 607, -1, 608, 5, {0}, "+VLS=17\r"},
- {RSP_OK, 608, 608, -1, 609, -1},
- {RSP_ZSAU, 609, 609, ZSAU_PROCEEDING, 610, 5, {ACT_CMD + AT_DIAL} },
- {RSP_OK, 610, 610, -1, 650, 0, {ACT_DIALING} },
-
- {RSP_ERROR, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} },
- {EV_TIMEOUT, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} },
+ {EV_DIAL, -1, -1, -1, -1, -1, {ACT_DIAL} },
+ {RSP_INIT, 0, 0, SEQ_DIAL, 601, 5, {ACT_CMD + AT_BC} },
+ {RSP_OK, 601, 601, -1, 603, 5, {ACT_CMD + AT_PROTO} },
+ {RSP_OK, 603, 603, -1, 604, 5, {ACT_CMD + AT_TYPE} },
+ {RSP_OK, 604, 604, -1, 605, 5, {ACT_CMD + AT_MSN} },
+ {RSP_NULL, 605, 605, -1, 606, 5, {ACT_CMD + AT_CLIP} },
+ {RSP_OK, 605, 605, -1, 606, 5, {ACT_CMD + AT_CLIP} },
+ {RSP_NULL, 606, 606, -1, 607, 5, {ACT_CMD + AT_ISO} },
+ {RSP_OK, 606, 606, -1, 607, 5, {ACT_CMD + AT_ISO} },
+ {RSP_OK, 607, 607, -1, 608, 5, {0}, "+VLS=17\r"},
+ {RSP_OK, 608, 608, -1, 609, -1},
+ {RSP_ZSAU, 609, 609, ZSAU_PROCEEDING, 610, 5, {ACT_CMD + AT_DIAL} },
+ {RSP_OK, 610, 610, -1, 650, 0, {ACT_DIALING} },
+
+ {RSP_ERROR, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} },
+ {EV_TIMEOUT, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} },
/* optional dialing responses */
- {EV_BC_OPEN, 650, 650, -1, 651, -1},
- {RSP_ZVLS, 609, 651, 17, -1, -1, {ACT_DEBUG} },
- {RSP_ZCTP, 610, 651, -1, -1, -1, {ACT_DEBUG} },
- {RSP_ZCPN, 610, 651, -1, -1, -1, {ACT_DEBUG} },
- {RSP_ZSAU, 650, 651, ZSAU_CALL_DELIVERED, -1, -1, {ACT_DEBUG} },
+ {EV_BC_OPEN, 650, 650, -1, 651, -1},
+ {RSP_ZVLS, 609, 651, 17, -1, -1, {ACT_DEBUG} },
+ {RSP_ZCTP, 610, 651, -1, -1, -1, {ACT_DEBUG} },
+ {RSP_ZCPN, 610, 651, -1, -1, -1, {ACT_DEBUG} },
+ {RSP_ZSAU, 650, 651, ZSAU_CALL_DELIVERED, -1, -1, {ACT_DEBUG} },
/* connect */
- {RSP_ZSAU, 650, 650, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} },
- {RSP_ZSAU, 651, 651, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT,
- ACT_NOTIFY_BC_UP} },
- {RSP_ZSAU, 750, 750, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} },
- {RSP_ZSAU, 751, 751, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT,
- ACT_NOTIFY_BC_UP} },
- {EV_BC_OPEN, 800, 800, -1, 800, -1, {ACT_NOTIFY_BC_UP} },
+ {RSP_ZSAU, 650, 650, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} },
+ {RSP_ZSAU, 651, 651, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT,
+ ACT_NOTIFY_BC_UP} },
+ {RSP_ZSAU, 750, 750, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} },
+ {RSP_ZSAU, 751, 751, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT,
+ ACT_NOTIFY_BC_UP} },
+ {EV_BC_OPEN, 800, 800, -1, 800, -1, {ACT_NOTIFY_BC_UP} },
/* remote hangup */
- {RSP_ZSAU, 650, 651, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT} },
- {RSP_ZSAU, 750, 751, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} },
- {RSP_ZSAU, 800, 800, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} },
+ {RSP_ZSAU, 650, 651, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT} },
+ {RSP_ZSAU, 750, 751, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} },
+ {RSP_ZSAU, 800, 800, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} },
/* hangup */
- {EV_HUP, -1, -1, -1, -1, -1, {ACT_HUP} },
- {RSP_INIT, -1, -1, SEQ_HUP, 401, 5, {0}, "+VLS=0\r"},
- {RSP_OK, 401, 401, -1, 402, 5},
- {RSP_ZVLS, 402, 402, 0, 403, 5},
- {RSP_ZSAU, 403, 403, ZSAU_DISCONNECT_REQ, -1, -1, {ACT_DEBUG} },
- {RSP_ZSAU, 403, 403, ZSAU_NULL, 0, 0, {ACT_DISCONNECT} },
- {RSP_NODEV, 401, 403, -1, 0, 0, {ACT_FAKEHUP} },
- {RSP_ERROR, 401, 401, -1, 0, 0, {ACT_ABORTHUP} },
- {EV_TIMEOUT, 401, 403, -1, 0, 0, {ACT_ABORTHUP} },
-
- {EV_BC_CLOSED, 0, 0, -1, 0, -1, {ACT_NOTIFY_BC_DOWN} },
+ {EV_HUP, -1, -1, -1, -1, -1, {ACT_HUP} },
+ {RSP_INIT, -1, -1, SEQ_HUP, 401, 5, {0}, "+VLS=0\r"},
+ {RSP_OK, 401, 401, -1, 402, 5},
+ {RSP_ZVLS, 402, 402, 0, 403, 5},
+ {RSP_ZSAU, 403, 403, ZSAU_DISCONNECT_REQ, -1, -1, {ACT_DEBUG} },
+ {RSP_ZSAU, 403, 403, ZSAU_NULL, 0, 0, {ACT_DISCONNECT} },
+ {RSP_NODEV, 401, 403, -1, 0, 0, {ACT_FAKEHUP} },
+ {RSP_ERROR, 401, 401, -1, 0, 0, {ACT_ABORTHUP} },
+ {EV_TIMEOUT, 401, 403, -1, 0, 0, {ACT_ABORTHUP} },
+
+ {EV_BC_CLOSED, 0, 0, -1, 0, -1, {ACT_NOTIFY_BC_DOWN} },
/* ring */
- {RSP_ZBC, 700, 700, -1, -1, -1, {0} },
- {RSP_ZHLC, 700, 700, -1, -1, -1, {0} },
- {RSP_NMBR, 700, 700, -1, -1, -1, {0} },
- {RSP_ZCPN, 700, 700, -1, -1, -1, {0} },
- {RSP_ZCTP, 700, 700, -1, -1, -1, {0} },
- {EV_TIMEOUT, 700, 700, -1, 720, 720, {ACT_ICALL} },
- {EV_BC_CLOSED, 720, 720, -1, 0, -1, {ACT_NOTIFY_BC_DOWN} },
+ {RSP_ZBC, 700, 700, -1, -1, -1, {0} },
+ {RSP_ZHLC, 700, 700, -1, -1, -1, {0} },
+ {RSP_NMBR, 700, 700, -1, -1, -1, {0} },
+ {RSP_ZCPN, 700, 700, -1, -1, -1, {0} },
+ {RSP_ZCTP, 700, 700, -1, -1, -1, {0} },
+ {EV_TIMEOUT, 700, 700, -1, 720, 720, {ACT_ICALL} },
+ {EV_BC_CLOSED, 720, 720, -1, 0, -1, {ACT_NOTIFY_BC_DOWN} },
/*accept icall*/
- {EV_ACCEPT, -1, -1, -1, -1, -1, {ACT_ACCEPT} },
- {RSP_INIT, 720, 720, SEQ_ACCEPT, 721, 5, {ACT_CMD + AT_PROTO} },
- {RSP_OK, 721, 721, -1, 722, 5, {ACT_CMD + AT_ISO} },
- {RSP_OK, 722, 722, -1, 723, 5, {0}, "+VLS=17\r"},
- {RSP_OK, 723, 723, -1, 724, 5, {0} },
- {RSP_ZVLS, 724, 724, 17, 750, 50, {ACT_ACCEPTED} },
- {RSP_ERROR, 721, 729, -1, 0, 0, {ACT_ABORTACCEPT} },
- {EV_TIMEOUT, 721, 729, -1, 0, 0, {ACT_ABORTACCEPT} },
- {RSP_ZSAU, 700, 729, ZSAU_NULL, 0, 0, {ACT_ABORTACCEPT} },
- {RSP_ZSAU, 700, 729, ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT} },
- {RSP_ZSAU, 700, 729, ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT} },
-
- {EV_BC_OPEN, 750, 750, -1, 751, -1},
- {EV_TIMEOUT, 750, 751, -1, 0, 0, {ACT_CONNTIMEOUT} },
+ {EV_ACCEPT, -1, -1, -1, -1, -1, {ACT_ACCEPT} },
+ {RSP_INIT, 720, 720, SEQ_ACCEPT, 721, 5, {ACT_CMD + AT_PROTO} },
+ {RSP_OK, 721, 721, -1, 722, 5, {ACT_CMD + AT_ISO} },
+ {RSP_OK, 722, 722, -1, 723, 5, {0}, "+VLS=17\r"},
+ {RSP_OK, 723, 723, -1, 724, 5, {0} },
+ {RSP_ZVLS, 724, 724, 17, 750, 50, {ACT_ACCEPTED} },
+ {RSP_ERROR, 721, 729, -1, 0, 0, {ACT_ABORTACCEPT} },
+ {EV_TIMEOUT, 721, 729, -1, 0, 0, {ACT_ABORTACCEPT} },
+ {RSP_ZSAU, 700, 729, ZSAU_NULL, 0, 0, {ACT_ABORTACCEPT} },
+ {RSP_ZSAU, 700, 729, ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT} },
+ {RSP_ZSAU, 700, 729, ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT} },
+
+ {EV_BC_OPEN, 750, 750, -1, 751, -1},
+ {EV_TIMEOUT, 750, 751, -1, 0, 0, {ACT_CONNTIMEOUT} },
/* B channel closed (general case) */
- {EV_BC_CLOSED, -1, -1, -1, -1, -1, {ACT_NOTIFY_BC_DOWN} },
+ {EV_BC_CLOSED, -1, -1, -1, -1, -1, {ACT_NOTIFY_BC_DOWN} },
/* misc. */
- {RSP_ZCON, -1, -1, -1, -1, -1, {ACT_DEBUG} },
- {RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} },
- {RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} },
- {RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} },
+ {RSP_ZCON, -1, -1, -1, -1, -1, {ACT_DEBUG} },
+ {RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} },
+ {RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} },
+ {RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} },
{RSP_LAST}
};
@@ -648,16 +649,16 @@ static void disconnect(struct at_state_t **at_state_p)
static inline struct at_state_t *get_free_channel(struct cardstate *cs,
int cid)
/* cids: >0: siemens-cid
- 0: without cid
- -1: no cid assigned yet
-*/
+ * 0: without cid
+ * -1: no cid assigned yet
+ */
{
unsigned long flags;
int i;
struct at_state_t *ret;
for (i = 0; i < cs->channels; ++i)
- if (gigaset_get_channel(cs->bcs + i)) {
+ if (gigaset_get_channel(cs->bcs + i) >= 0) {
ret = &cs->bcs[i].at_state;
ret->cid = cid;
return ret;
@@ -922,18 +923,18 @@ static void do_stop(struct cardstate *cs)
* channel >= 0: getting cid for the channel failed
* channel < 0: entering cid mode failed
*
- * returns 0 on failure
+ * returns 0 on success, <0 on failure
*/
static int reinit_and_retry(struct cardstate *cs, int channel)
{
int i;
if (--cs->retry_count <= 0)
- return 0;
+ return -EFAULT;
for (i = 0; i < cs->channels; ++i)
if (cs->bcs[i].at_state.cid > 0)
- return 0;
+ return -EBUSY;
if (channel < 0)
dev_warn(cs->dev,
@@ -944,7 +945,7 @@ static int reinit_and_retry(struct cardstate *cs, int channel)
cs->bcs[channel].at_state.pending_commands |= PC_CID;
}
schedule_init(cs, MS_INIT);
- return 1;
+ return 0;
}
static int at_state_invalid(struct cardstate *cs,
@@ -1015,7 +1016,7 @@ static int do_lock(struct cardstate *cs)
if (cs->bcs[i].at_state.pending_commands)
return -EBUSY;
- if (!gigaset_get_channels(cs))
+ if (gigaset_get_channels(cs) < 0)
return -EBUSY;
break;
@@ -1124,7 +1125,7 @@ static void do_action(int action, struct cardstate *cs,
init_failed(cs, M_UNKNOWN);
break;
}
- if (!reinit_and_retry(cs, -1))
+ if (reinit_and_retry(cs, -1) < 0)
schedule_init(cs, MS_RECOVER);
break;
case ACT_FAILUMODE:
@@ -1267,7 +1268,7 @@ static void do_action(int action, struct cardstate *cs,
case ACT_FAILCID:
cs->cur_at_seq = SEQ_NONE;
channel = cs->curchannel;
- if (!reinit_and_retry(cs, channel)) {
+ if (reinit_and_retry(cs, channel) < 0) {
dev_warn(cs->dev,
"Could not get a call ID. Cannot dial.\n");
at_state2 = &cs->bcs[channel].at_state;
@@ -1314,8 +1315,9 @@ static void do_action(int action, struct cardstate *cs,
s = ev->ptr;
if (!strcmp(s, "OK")) {
+ /* OK without version string: assume old response */
*p_genresp = 1;
- *p_resp_code = RSP_ERROR;
+ *p_resp_code = RSP_NONE;
break;
}
@@ -1372,7 +1374,8 @@ static void do_action(int action, struct cardstate *cs,
ev->parameter, at_state->ConState);
break;
- /* events from the LL */
+ /* events from the LL */
+
case ACT_DIAL:
start_dial(at_state, ev->ptr, ev->parameter);
break;
@@ -1385,7 +1388,8 @@ static void do_action(int action, struct cardstate *cs,
cs->commands_pending = 1;
break;
- /* hotplug events */
+ /* hotplug events */
+
case ACT_STOP:
do_stop(cs);
break;
@@ -1393,7 +1397,8 @@ static void do_action(int action, struct cardstate *cs,
do_start(cs);
break;
- /* events from the interface */
+ /* events from the interface */
+
case ACT_IF_LOCK:
cs->cmd_result = ev->parameter ? do_lock(cs) : do_unlock(cs);
cs->waiting = 0;
@@ -1412,7 +1417,8 @@ static void do_action(int action, struct cardstate *cs,
wake_up(&cs->waitqueue);
break;
- /* events from the proc file system */
+ /* events from the proc file system */
+
case ACT_PROC_CIDMODE:
spin_lock_irqsave(&cs->lock, flags);
if (ev->parameter != cs->cidmode) {
@@ -1431,7 +1437,8 @@ static void do_action(int action, struct cardstate *cs,
wake_up(&cs->waitqueue);
break;
- /* events from the hardware drivers */
+ /* events from the hardware drivers */
+
case ACT_NOTIFY_BC_DOWN:
bchannel_down(bcs);
break;
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index 1dc25131e670..8e2fc8f31d16 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -163,8 +163,8 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
#define BAS_LOWFRAME 5 /* " " with negative flow control */
#define BAS_CORRFRAMES 4 /* flow control multiplicator */
-#define BAS_INBUFSIZE (BAS_MAXFRAME * BAS_NUMFRAMES)
-/* size of isoc in buf per URB */
+#define BAS_INBUFSIZE (BAS_MAXFRAME * BAS_NUMFRAMES) /* size of isoc in buf
+ * per URB */
#define BAS_OUTBUFSIZE 4096 /* size of common isoc out buffer */
#define BAS_OUTBUFPAD BAS_MAXFRAME /* size of pad area for isoc out buf */
@@ -471,18 +471,18 @@ struct cardstate {
for */
int commands_pending; /* flag(s) in xxx.commands_pending have
been set */
- struct tasklet_struct event_tasklet;
- /* tasklet for serializing AT commands.
- * Scheduled
- * -> for modem reponses (and
- * incoming data for M10x)
- * -> on timeout
- * -> after setting bits in
- * xxx.at_state.pending_command
- * (e.g. command from LL) */
- struct tasklet_struct write_tasklet;
- /* tasklet for serial output
- * (not used in base driver) */
+ struct tasklet_struct
+ event_tasklet; /* tasklet for serializing AT commands.
+ * Scheduled
+ * -> for modem reponses (and
+ * incoming data for M10x)
+ * -> on timeout
+ * -> after setting bits in
+ * xxx.at_state.pending_command
+ * (e.g. command from LL) */
+ struct tasklet_struct
+ write_tasklet; /* tasklet for serial output
+ * (not used in base driver) */
/* event queue */
struct event_t events[MAX_EVENTS];
@@ -583,7 +583,7 @@ struct gigaset_ops {
int (*initbcshw)(struct bc_state *bcs);
/* Called by gigaset_freecs() for freeing bcs->hw.xxx */
- int (*freebcshw)(struct bc_state *bcs);
+ void (*freebcshw)(struct bc_state *bcs);
/* Called by gigaset_bchannel_down() for resetting bcs->hw.xxx */
void (*reinitbcshw)(struct bc_state *bcs);
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c
index 0f13eb1de657..2d75329007f1 100644
--- a/drivers/isdn/gigaset/i4l.c
+++ b/drivers/isdn/gigaset/i4l.c
@@ -229,7 +229,7 @@ static int command_from_LL(isdn_ctrl *cntrl)
return -EINVAL;
}
bcs = cs->bcs + ch;
- if (!gigaset_get_channel(bcs)) {
+ if (gigaset_get_channel(bcs) < 0) {
dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n");
return -EBUSY;
}
@@ -618,7 +618,7 @@ void gigaset_isdn_stop(struct cardstate *cs)
* @cs: device descriptor structure.
* @isdnid: device name.
*
- * Return value: 1 for success, 0 for failure
+ * Return value: 0 on success, error code < 0 on failure
*/
int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
{
@@ -627,14 +627,14 @@ int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
iif = kmalloc(sizeof *iif, GFP_KERNEL);
if (!iif) {
pr_err("out of memory\n");
- return 0;
+ return -ENOMEM;
}
if (snprintf(iif->id, sizeof iif->id, "%s_%u", isdnid, cs->minor_index)
>= sizeof iif->id) {
pr_err("ID too long: %s\n", isdnid);
kfree(iif);
- return 0;
+ return -EINVAL;
}
iif->owner = THIS_MODULE;
@@ -656,13 +656,13 @@ int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
if (!register_isdn(iif)) {
pr_err("register_isdn failed\n");
kfree(iif);
- return 0;
+ return -EINVAL;
}
cs->iif = iif;
cs->myid = iif->channels; /* Set my device id */
cs->hw_hdr_len = HW_HDR_LEN;
- return 1;
+ return 0;
}
/**
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c
index a351c16705bd..bc29f1d52a2f 100644
--- a/drivers/isdn/gigaset/isocdata.c
+++ b/drivers/isdn/gigaset/isocdata.c
@@ -56,7 +56,7 @@ static inline int isowbuf_freebytes(struct isowbuf_t *iwb)
/* start writing
* acquire the write semaphore
- * return true if acquired, false if busy
+ * return 0 if acquired, <0 if busy
*/
static inline int isowbuf_startwrite(struct isowbuf_t *iwb)
{
@@ -64,12 +64,12 @@ static inline int isowbuf_startwrite(struct isowbuf_t *iwb)
atomic_inc(&iwb->writesem);
gig_dbg(DEBUG_ISO, "%s: couldn't acquire iso write semaphore",
__func__);
- return 0;
+ return -EBUSY;
}
gig_dbg(DEBUG_ISO,
"%s: acquired iso write semaphore, data[write]=%02x, nbits=%d",
__func__, iwb->data[iwb->write], iwb->wbits);
- return 1;
+ return 0;
}
/* finish writing
@@ -158,7 +158,7 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size)
/* no wraparound in valid data */
if (limit >= write) {
/* append idle frame */
- if (!isowbuf_startwrite(iwb))
+ if (isowbuf_startwrite(iwb) < 0)
return -EBUSY;
/* write position could have changed */
write = iwb->write;
@@ -403,7 +403,7 @@ static inline int hdlc_buildframe(struct isowbuf_t *iwb,
unsigned char c;
if (isowbuf_freebytes(iwb) < count + count / 5 + 6 ||
- !isowbuf_startwrite(iwb)) {
+ isowbuf_startwrite(iwb) < 0) {
gig_dbg(DEBUG_ISO, "%s: %d bytes free -> -EAGAIN",
__func__, isowbuf_freebytes(iwb));
return -EAGAIN;
@@ -457,7 +457,7 @@ static inline int trans_buildframe(struct isowbuf_t *iwb,
return iwb->write;
if (isowbuf_freebytes(iwb) < count ||
- !isowbuf_startwrite(iwb)) {
+ isowbuf_startwrite(iwb) < 0) {
gig_dbg(DEBUG_ISO, "can't put %d bytes", count);
return -EAGAIN;
}
diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c
index 6f3fd4cf4378..8c91fd5eb6fd 100644
--- a/drivers/isdn/gigaset/ser-gigaset.c
+++ b/drivers/isdn/gigaset/ser-gigaset.c
@@ -340,17 +340,16 @@ static int gigaset_initbcshw(struct bc_state *bcs)
{
/* unused */
bcs->hw.ser = NULL;
- return 1;
+ return 0;
}
/*
* Free B channel structure
* Called by "gigaset_freebcs" in common.c
*/
-static int gigaset_freebcshw(struct bc_state *bcs)
+static void gigaset_freebcshw(struct bc_state *bcs)
{
/* unused */
- return 1;
}
/*
@@ -398,7 +397,7 @@ static int gigaset_initcshw(struct cardstate *cs)
scs = kzalloc(sizeof(struct ser_cardstate), GFP_KERNEL);
if (!scs) {
pr_err("out of memory\n");
- return 0;
+ return -ENOMEM;
}
cs->hw.ser = scs;
@@ -410,13 +409,13 @@ static int gigaset_initcshw(struct cardstate *cs)
pr_err("error %d registering platform device\n", rc);
kfree(cs->hw.ser);
cs->hw.ser = NULL;
- return 0;
+ return rc;
}
dev_set_drvdata(&cs->hw.ser->dev.dev, cs);
tasklet_init(&cs->write_tasklet,
gigaset_modem_fill, (unsigned long) cs);
- return 1;
+ return 0;
}
/*
@@ -503,6 +502,7 @@ static int
gigaset_tty_open(struct tty_struct *tty)
{
struct cardstate *cs;
+ int rc;
gig_dbg(DEBUG_INIT, "Starting HLL for Gigaset M101");
@@ -515,8 +515,10 @@ gigaset_tty_open(struct tty_struct *tty)
/* allocate memory for our device state and initialize it */
cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME);
- if (!cs)
+ if (!cs) {
+ rc = -ENODEV;
goto error;
+ }
cs->dev = &cs->hw.ser->dev.dev;
cs->hw.ser->tty = tty;
@@ -530,7 +532,8 @@ gigaset_tty_open(struct tty_struct *tty)
*/
if (startmode == SM_LOCKED)
cs->mstate = MS_LOCKED;
- if (!gigaset_start(cs)) {
+ rc = gigaset_start(cs);
+ if (rc < 0) {
tasklet_kill(&cs->write_tasklet);
goto error;
}
@@ -542,7 +545,7 @@ error:
gig_dbg(DEBUG_INIT, "Startup of HLL failed");
tty->disc_data = NULL;
gigaset_freecs(cs);
- return -ENODEV;
+ return rc;
}
/*
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c
index 78f81e8a5be6..d0a41cb0cf62 100644
--- a/drivers/isdn/gigaset/usb-gigaset.c
+++ b/drivers/isdn/gigaset/usb-gigaset.c
@@ -550,10 +550,9 @@ static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6])
0, 0, &buf, 6, 2000);
}
-static int gigaset_freebcshw(struct bc_state *bcs)
+static void gigaset_freebcshw(struct bc_state *bcs)
{
/* unused */
- return 1;
}
/* Initialize the b-channel structure */
@@ -561,7 +560,7 @@ static int gigaset_initbcshw(struct bc_state *bcs)
{
/* unused */
bcs->hw.usb = NULL;
- return 1;
+ return 0;
}
static void gigaset_reinitbcshw(struct bc_state *bcs)
@@ -583,7 +582,7 @@ static int gigaset_initcshw(struct cardstate *cs)
kmalloc(sizeof(struct usb_cardstate), GFP_KERNEL);
if (!ucs) {
pr_err("out of memory\n");
- return 0;
+ return -ENOMEM;
}
ucs->bchars[0] = 0;
@@ -598,7 +597,7 @@ static int gigaset_initcshw(struct cardstate *cs)
tasklet_init(&cs->write_tasklet,
gigaset_modem_fill, (unsigned long) cs);
- return 1;
+ return 0;
}
/* Send data from current skb to the device. */
@@ -767,9 +766,9 @@ static int gigaset_probe(struct usb_interface *interface,
if (startmode == SM_LOCKED)
cs->mstate = MS_LOCKED;
- if (!gigaset_start(cs)) {
+ retval = gigaset_start(cs);
+ if (retval < 0) {
tasklet_kill(&cs->write_tasklet);
- retval = -ENODEV;
goto error;
}
return 0;
@@ -899,8 +898,10 @@ static int __init usb_gigaset_init(void)
driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
GIGASET_MODULENAME, GIGASET_DEVNAME,
&ops, THIS_MODULE);
- if (driver == NULL)
+ if (driver == NULL) {
+ result = -ENOMEM;
goto error;
+ }
/* register this driver with the USB subsystem */
result = usb_register(&gigaset_usb_driver);
@@ -916,7 +917,7 @@ error:
if (driver)
gigaset_freedriver(driver);
driver = NULL;
- return -1;
+ return result;
}
/*
diff --git a/drivers/isdn/hardware/eicon/capifunc.c b/drivers/isdn/hardware/eicon/capifunc.c
index a576f32e6635..7a0bdbdd87ea 100644
--- a/drivers/isdn/hardware/eicon/capifunc.c
+++ b/drivers/isdn/hardware/eicon/capifunc.c
@@ -1120,7 +1120,7 @@ int fax_head_line_time(char *buffer)
/*
* init (alloc) main structures
*/
-static int DIVA_INIT_FUNCTION init_main_structs(void)
+static int __init init_main_structs(void)
{
if (!(mapped_msg = (CAPI_MSG *) diva_os_malloc(0, MAX_MSG_SIZE))) {
DBG_ERR(("init: failed alloc mapped_msg."))
@@ -1181,7 +1181,7 @@ static void do_api_remove_start(void)
/*
* init
*/
-int DIVA_INIT_FUNCTION init_capifunc(void)
+int __init init_capifunc(void)
{
diva_os_initialize_spin_lock(&api_lock, "capifunc");
memset(ControllerMap, 0, MAX_DESCRIPTORS + 1);
@@ -1209,7 +1209,7 @@ int DIVA_INIT_FUNCTION init_capifunc(void)
/*
* finit
*/
-void DIVA_EXIT_FUNCTION finit_capifunc(void)
+void __exit finit_capifunc(void)
{
do_api_remove_start();
divacapi_disconnect_didd();
diff --git a/drivers/isdn/hardware/eicon/capimain.c b/drivers/isdn/hardware/eicon/capimain.c
index eabe0fa1b627..997d46abf5b2 100644
--- a/drivers/isdn/hardware/eicon/capimain.c
+++ b/drivers/isdn/hardware/eicon/capimain.c
@@ -118,7 +118,7 @@ void diva_os_set_controller_struct(struct capi_ctr *ctrl)
/*
* module init
*/
-static int DIVA_INIT_FUNCTION divacapi_init(void)
+static int __init divacapi_init(void)
{
char tmprev[32];
int ret = 0;
@@ -144,7 +144,7 @@ static int DIVA_INIT_FUNCTION divacapi_init(void)
/*
* module exit
*/
-static void DIVA_EXIT_FUNCTION divacapi_exit(void)
+static void __exit divacapi_exit(void)
{
finit_capifunc();
printk(KERN_INFO "%s: module unloaded.\n", DRIVERLNAME);
diff --git a/drivers/isdn/hardware/eicon/diddfunc.c b/drivers/isdn/hardware/eicon/diddfunc.c
index c4c8220c9d72..b0b23ed8b374 100644
--- a/drivers/isdn/hardware/eicon/diddfunc.c
+++ b/drivers/isdn/hardware/eicon/diddfunc.c
@@ -47,7 +47,7 @@ static void *didd_callback(void *context, DESCRIPTOR *adapter,
/*
* connect to didd
*/
-static int DIVA_INIT_FUNCTION connect_didd(void)
+static int __init connect_didd(void)
{
int x = 0;
int dadapter = 0;
@@ -79,7 +79,7 @@ static int DIVA_INIT_FUNCTION connect_didd(void)
/*
* disconnect from didd
*/
-static void DIVA_EXIT_FUNCTION disconnect_didd(void)
+static void __exit disconnect_didd(void)
{
IDI_SYNC_REQ req;
@@ -92,7 +92,7 @@ static void DIVA_EXIT_FUNCTION disconnect_didd(void)
/*
* init
*/
-int DIVA_INIT_FUNCTION diddfunc_init(void)
+int __init diddfunc_init(void)
{
diva_didd_load_time_init();
@@ -107,7 +107,7 @@ int DIVA_INIT_FUNCTION diddfunc_init(void)
/*
* finit
*/
-void DIVA_EXIT_FUNCTION diddfunc_finit(void)
+void __exit diddfunc_finit(void)
{
DbgDeregister();
disconnect_didd();
diff --git a/drivers/isdn/hardware/eicon/diva_didd.c b/drivers/isdn/hardware/eicon/diva_didd.c
index d1d3de03cced..fab6ccfb00d5 100644
--- a/drivers/isdn/hardware/eicon/diva_didd.c
+++ b/drivers/isdn/hardware/eicon/diva_didd.c
@@ -91,7 +91,7 @@ static const struct file_operations divadidd_proc_fops = {
.release = single_release,
};
-static int DIVA_INIT_FUNCTION create_proc(void)
+static int __init create_proc(void)
{
proc_net_eicon = proc_mkdir("eicon", init_net.proc_net);
@@ -109,7 +109,7 @@ static void remove_proc(void)
remove_proc_entry("eicon", init_net.proc_net);
}
-static int DIVA_INIT_FUNCTION divadidd_init(void)
+static int __init divadidd_init(void)
{
char tmprev[32];
int ret = 0;
@@ -141,7 +141,7 @@ out:
return (ret);
}
-static void DIVA_EXIT_FUNCTION divadidd_exit(void)
+static void __exit divadidd_exit(void)
{
diddfunc_finit();
remove_proc();
diff --git a/drivers/isdn/hardware/eicon/divamnt.c b/drivers/isdn/hardware/eicon/divamnt.c
index ffa0c31be745..48db08d0bb3d 100644
--- a/drivers/isdn/hardware/eicon/divamnt.c
+++ b/drivers/isdn/hardware/eicon/divamnt.c
@@ -184,7 +184,7 @@ static void divas_maint_unregister_chrdev(void)
unregister_chrdev(major, DEVNAME);
}
-static int DIVA_INIT_FUNCTION divas_maint_register_chrdev(void)
+static int __init divas_maint_register_chrdev(void)
{
if ((major = register_chrdev(0, DEVNAME, &divas_maint_fops)) < 0)
{
@@ -207,7 +207,7 @@ void diva_maint_wakeup_read(void)
/*
* Driver Load
*/
-static int DIVA_INIT_FUNCTION maint_init(void)
+static int __init maint_init(void)
{
char tmprev[50];
int ret = 0;
@@ -245,7 +245,7 @@ out:
/*
** Driver Unload
*/
-static void DIVA_EXIT_FUNCTION maint_exit(void)
+static void __exit maint_exit(void)
{
divas_maint_unregister_chrdev();
mntfunc_finit();
diff --git a/drivers/isdn/hardware/eicon/divasfunc.c b/drivers/isdn/hardware/eicon/divasfunc.c
index 60aaf9580956..4be5f8814777 100644
--- a/drivers/isdn/hardware/eicon/divasfunc.c
+++ b/drivers/isdn/hardware/eicon/divasfunc.c
@@ -153,7 +153,7 @@ static void *didd_callback(void *context, DESCRIPTOR *adapter,
/*
* connect to didd
*/
-static int DIVA_INIT_FUNCTION connect_didd(void)
+static int __init connect_didd(void)
{
int x = 0;
int dadapter = 0;
@@ -209,7 +209,7 @@ static void disconnect_didd(void)
/*
* init
*/
-int DIVA_INIT_FUNCTION divasfunc_init(int dbgmask)
+int __init divasfunc_init(int dbgmask)
{
char *version;
diff --git a/drivers/isdn/hardware/eicon/divasi.c b/drivers/isdn/hardware/eicon/divasi.c
index a5c8f90b3b37..4103a8c178d7 100644
--- a/drivers/isdn/hardware/eicon/divasi.c
+++ b/drivers/isdn/hardware/eicon/divasi.c
@@ -114,7 +114,7 @@ static const struct file_operations um_idi_proc_fops = {
.release = single_release,
};
-static int DIVA_INIT_FUNCTION create_um_idi_proc(void)
+static int __init create_um_idi_proc(void)
{
um_idi_proc_entry = proc_create(DRIVERLNAME, S_IRUGO, proc_net_eicon,
&um_idi_proc_fops);
@@ -146,7 +146,7 @@ static void divas_idi_unregister_chrdev(void)
unregister_chrdev(major, DEVNAME);
}
-static int DIVA_INIT_FUNCTION divas_idi_register_chrdev(void)
+static int __init divas_idi_register_chrdev(void)
{
if ((major = register_chrdev(0, DEVNAME, &divas_idi_fops)) < 0)
{
@@ -161,7 +161,7 @@ static int DIVA_INIT_FUNCTION divas_idi_register_chrdev(void)
/*
** Driver Load
*/
-static int DIVA_INIT_FUNCTION divasi_init(void)
+static int __init divasi_init(void)
{
char tmprev[50];
int ret = 0;
@@ -202,7 +202,7 @@ out:
/*
** Driver Unload
*/
-static void DIVA_EXIT_FUNCTION divasi_exit(void)
+static void __exit divasi_exit(void)
{
idifunc_finit();
remove_um_idi_proc();
diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c
index 7eaab06276f9..ca6d276bb256 100644
--- a/drivers/isdn/hardware/eicon/divasmain.c
+++ b/drivers/isdn/hardware/eicon/divasmain.c
@@ -673,7 +673,7 @@ static void divas_unregister_chrdev(void)
unregister_chrdev(major, DEVNAME);
}
-static int DIVA_INIT_FUNCTION divas_register_chrdev(void)
+static int __init divas_register_chrdev(void)
{
if ((major = register_chrdev(0, DEVNAME, &divas_fops)) < 0)
{
@@ -767,7 +767,7 @@ static void __devexit divas_remove_one(struct pci_dev *pdev)
/* --------------------------------------------------------------------------
Driver Load / Startup
-------------------------------------------------------------------------- */
-static int DIVA_INIT_FUNCTION divas_init(void)
+static int __init divas_init(void)
{
char tmprev[50];
int ret = 0;
@@ -831,7 +831,7 @@ out:
/* --------------------------------------------------------------------------
Driver Unload
-------------------------------------------------------------------------- */
-static void DIVA_EXIT_FUNCTION divas_exit(void)
+static void __exit divas_exit(void)
{
pci_unregister_driver(&diva_pci_driver);
remove_divas_proc();
diff --git a/drivers/isdn/hardware/eicon/idifunc.c b/drivers/isdn/hardware/eicon/idifunc.c
index d153e3cdecf7..fef6586fe5ac 100644
--- a/drivers/isdn/hardware/eicon/idifunc.c
+++ b/drivers/isdn/hardware/eicon/idifunc.c
@@ -133,7 +133,7 @@ static void um_remove_card(DESCRIPTOR *d)
/*
* remove all adapter
*/
-static void DIVA_EXIT_FUNCTION remove_all_idi_proc(void)
+static void __exit remove_all_idi_proc(void)
{
udiva_card *card;
diva_os_spin_lock_magic_t old_irql;
@@ -181,7 +181,7 @@ static void *didd_callback(void *context, DESCRIPTOR *adapter,
/*
* connect DIDD
*/
-static int DIVA_INIT_FUNCTION connect_didd(void)
+static int __init connect_didd(void)
{
int x = 0;
int dadapter = 0;
@@ -225,7 +225,7 @@ static int DIVA_INIT_FUNCTION connect_didd(void)
/*
* Disconnect from DIDD
*/
-static void DIVA_EXIT_FUNCTION disconnect_didd(void)
+static void __exit disconnect_didd(void)
{
IDI_SYNC_REQ req;
@@ -240,7 +240,7 @@ static void DIVA_EXIT_FUNCTION disconnect_didd(void)
/*
* init
*/
-int DIVA_INIT_FUNCTION idifunc_init(void)
+int __init idifunc_init(void)
{
diva_os_initialize_spin_lock(&ll_lock, "idifunc");
@@ -260,7 +260,7 @@ int DIVA_INIT_FUNCTION idifunc_init(void)
/*
* finit
*/
-void DIVA_EXIT_FUNCTION idifunc_finit(void)
+void __exit idifunc_finit(void)
{
diva_user_mode_idi_finit();
disconnect_didd();
diff --git a/drivers/isdn/hardware/eicon/mntfunc.c b/drivers/isdn/hardware/eicon/mntfunc.c
index d6072607305c..1cd9affb6058 100644
--- a/drivers/isdn/hardware/eicon/mntfunc.c
+++ b/drivers/isdn/hardware/eicon/mntfunc.c
@@ -72,7 +72,7 @@ static void *didd_callback(void *context, DESCRIPTOR *adapter,
/*
* connect to didd
*/
-static int DIVA_INIT_FUNCTION connect_didd(void)
+static int __init connect_didd(void)
{
int x = 0;
int dadapter = 0;
@@ -114,7 +114,7 @@ static int DIVA_INIT_FUNCTION connect_didd(void)
/*
* disconnect from didd
*/
-static void DIVA_EXIT_FUNCTION disconnect_didd(void)
+static void __exit disconnect_didd(void)
{
IDI_SYNC_REQ req;
@@ -300,7 +300,7 @@ int maint_read_write(void __user *buf, int count)
/*
* init
*/
-int DIVA_INIT_FUNCTION mntfunc_init(int *buffer_length, void **buffer,
+int __init mntfunc_init(int *buffer_length, void **buffer,
unsigned long diva_dbg_mem)
{
if (*buffer_length < 64) {
@@ -348,7 +348,7 @@ int DIVA_INIT_FUNCTION mntfunc_init(int *buffer_length, void **buffer,
/*
* exit
*/
-void DIVA_EXIT_FUNCTION mntfunc_finit(void)
+void __exit mntfunc_finit(void)
{
void *buffer;
int i = 100;
diff --git a/drivers/isdn/hardware/eicon/platform.h b/drivers/isdn/hardware/eicon/platform.h
index 7331c3b14a5f..b2edb7590dda 100644
--- a/drivers/isdn/hardware/eicon/platform.h
+++ b/drivers/isdn/hardware/eicon/platform.h
@@ -38,9 +38,6 @@
#define DIVA_NO_DEBUGLIB
#endif
-#define DIVA_INIT_FUNCTION __init
-#define DIVA_EXIT_FUNCTION __exit
-
#define DIVA_USER_MODE_CARD_CONFIG 1
#define USE_EXTENDED_DEBUGS 1
diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c
index c0b8c960ee3f..c08fc605e56b 100644
--- a/drivers/isdn/hardware/mISDN/avmfritz.c
+++ b/drivers/isdn/hardware/mISDN/avmfritz.c
@@ -30,7 +30,7 @@
#include "ipac.h"
-#define AVMFRITZ_REV "2.1"
+#define AVMFRITZ_REV "2.3"
static int AVM_cnt;
static int debug;
@@ -69,6 +69,7 @@ enum {
#define HDLC_MODE_TRANS 0x02
#define HDLC_MODE_CCR_7 0x04
#define HDLC_MODE_CCR_16 0x08
+#define HDLC_FIFO_SIZE_128 0x20
#define HDLC_MODE_TESTLOOP 0x80
#define HDLC_INT_XPR 0x80
@@ -80,13 +81,16 @@ enum {
#define HDLC_STAT_RDO 0x10
#define HDLC_STAT_CRCVFRRAB 0x0E
#define HDLC_STAT_CRCVFR 0x06
-#define HDLC_STAT_RML_MASK 0x3f00
+#define HDLC_STAT_RML_MASK_V1 0x3f00
+#define HDLC_STAT_RML_MASK_V2 0x7f00
#define HDLC_CMD_XRS 0x80
#define HDLC_CMD_XME 0x01
#define HDLC_CMD_RRS 0x20
#define HDLC_CMD_XML_MASK 0x3f00
-#define HDLC_FIFO_SIZE 32
+
+#define HDLC_FIFO_SIZE_V1 32
+#define HDLC_FIFO_SIZE_V2 128
/* Fritz PCI v2.0 */
@@ -346,11 +350,14 @@ modehdlc(struct bchannel *bch, int protocol)
{
struct fritzcard *fc = bch->hw;
struct hdlc_hw *hdlc;
+ u8 mode;
hdlc = &fc->hdlc[(bch->nr - 1) & 1];
pr_debug("%s: hdlc %c protocol %x-->%x ch %d\n", fc->name,
'@' + bch->nr, bch->state, protocol, bch->nr);
hdlc->ctrl.ctrl = 0;
+ mode = (fc->type == AVM_FRITZ_PCIV2) ? HDLC_FIFO_SIZE_128 : 0;
+
switch (protocol) {
case -1: /* used for init */
bch->state = -1;
@@ -358,7 +365,7 @@ modehdlc(struct bchannel *bch, int protocol)
if (bch->state == ISDN_P_NONE)
break;
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
- hdlc->ctrl.sr.mode = HDLC_MODE_TRANS;
+ hdlc->ctrl.sr.mode = mode | HDLC_MODE_TRANS;
write_ctrl(bch, 5);
bch->state = ISDN_P_NONE;
test_and_clear_bit(FLG_HDLC, &bch->Flags);
@@ -367,7 +374,7 @@ modehdlc(struct bchannel *bch, int protocol)
case ISDN_P_B_RAW:
bch->state = protocol;
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
- hdlc->ctrl.sr.mode = HDLC_MODE_TRANS;
+ hdlc->ctrl.sr.mode = mode | HDLC_MODE_TRANS;
write_ctrl(bch, 5);
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;
write_ctrl(bch, 1);
@@ -377,7 +384,7 @@ modehdlc(struct bchannel *bch, int protocol)
case ISDN_P_B_HDLC:
bch->state = protocol;
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
- hdlc->ctrl.sr.mode = HDLC_MODE_ITF_FLG;
+ hdlc->ctrl.sr.mode = mode | HDLC_MODE_ITF_FLG;
write_ctrl(bch, 5);
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;
write_ctrl(bch, 1);
@@ -397,39 +404,40 @@ hdlc_empty_fifo(struct bchannel *bch, int count)
u32 *ptr;
u8 *p;
u32 val, addr;
- int cnt = 0;
+ int cnt;
struct fritzcard *fc = bch->hw;
pr_debug("%s: %s %d\n", fc->name, __func__, count);
- if (!bch->rx_skb) {
- bch->rx_skb = mI_alloc_skb(bch->maxlen, GFP_ATOMIC);
- if (!bch->rx_skb) {
- pr_info("%s: B receive out of memory\n",
- fc->name);
+ if (test_bit(FLG_RX_OFF, &bch->Flags)) {
+ p = NULL;
+ bch->dropcnt += count;
+ } else {
+ cnt = bchannel_get_rxbuf(bch, count);
+ if (cnt < 0) {
+ pr_warning("%s.B%d: No bufferspace for %d bytes\n",
+ fc->name, bch->nr, count);
return;
}
+ p = skb_put(bch->rx_skb, count);
}
- if ((bch->rx_skb->len + count) > bch->maxlen) {
- pr_debug("%s: overrun %d\n", fc->name,
- bch->rx_skb->len + count);
- return;
- }
- p = skb_put(bch->rx_skb, count);
ptr = (u32 *)p;
- if (AVM_FRITZ_PCIV2 == fc->type)
+ if (fc->type == AVM_FRITZ_PCIV2)
addr = fc->addr + (bch->nr == 2 ?
AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1);
else {
addr = fc->addr + CHIP_WINDOW;
outl(bch->nr == 2 ? AVM_HDLC_2 : AVM_HDLC_1, fc->addr);
}
+ cnt = 0;
while (cnt < count) {
val = le32_to_cpu(inl(addr));
- put_unaligned(val, ptr);
- ptr++;
+ if (p) {
+ put_unaligned(val, ptr);
+ ptr++;
+ }
cnt += 4;
}
- if (debug & DEBUG_HW_BFIFO) {
+ if (p && (debug & DEBUG_HW_BFIFO)) {
snprintf(fc->log, LOG_SIZE, "B%1d-recv %s %d ",
bch->nr, fc->name, count);
print_hex_dump_bytes(fc->log, DUMP_PREFIX_OFFSET, p, count);
@@ -441,30 +449,43 @@ hdlc_fill_fifo(struct bchannel *bch)
{
struct fritzcard *fc = bch->hw;
struct hdlc_hw *hdlc;
- int count, cnt = 0;
+ int count, fs, cnt = 0, idx, fillempty = 0;
u8 *p;
u32 *ptr, val, addr;
- hdlc = &fc->hdlc[(bch->nr - 1) & 1];
- if (!bch->tx_skb)
- return;
- count = bch->tx_skb->len - bch->tx_idx;
- if (count <= 0)
- return;
- p = bch->tx_skb->data + bch->tx_idx;
+ idx = (bch->nr - 1) & 1;
+ hdlc = &fc->hdlc[idx];
+ fs = (fc->type == AVM_FRITZ_PCIV2) ?
+ HDLC_FIFO_SIZE_V2 : HDLC_FIFO_SIZE_V1;
+ if (!bch->tx_skb) {
+ if (!test_bit(FLG_TX_EMPTY, &bch->Flags))
+ return;
+ count = fs;
+ p = bch->fill;
+ fillempty = 1;
+ } else {
+ count = bch->tx_skb->len - bch->tx_idx;
+ if (count <= 0)
+ return;
+ p = bch->tx_skb->data + bch->tx_idx;
+ }
hdlc->ctrl.sr.cmd &= ~HDLC_CMD_XME;
- if (count > HDLC_FIFO_SIZE) {
- count = HDLC_FIFO_SIZE;
+ if (count > fs) {
+ count = fs;
} else {
if (test_bit(FLG_HDLC, &bch->Flags))
hdlc->ctrl.sr.cmd |= HDLC_CMD_XME;
}
- pr_debug("%s: %s %d/%d/%d", fc->name, __func__, count,
- bch->tx_idx, bch->tx_skb->len);
ptr = (u32 *)p;
- bch->tx_idx += count;
- hdlc->ctrl.sr.xml = ((count == HDLC_FIFO_SIZE) ? 0 : count);
- if (AVM_FRITZ_PCIV2 == fc->type) {
+ if (fillempty) {
+ pr_debug("%s.B%d: %d/%d/%d", fc->name, bch->nr, count,
+ bch->tx_idx, bch->tx_skb->len);
+ bch->tx_idx += count;
+ } else {
+ pr_debug("%s.B%d: fillempty %d\n", fc->name, bch->nr, count);
+ }
+ hdlc->ctrl.sr.xml = ((count == fs) ? 0 : count);
+ if (fc->type == AVM_FRITZ_PCIV2) {
__write_ctrl_pciv2(fc, hdlc, bch->nr);
addr = fc->addr + (bch->nr == 2 ?
AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1);
@@ -472,13 +493,21 @@ hdlc_fill_fifo(struct bchannel *bch)
__write_ctrl_pci(fc, hdlc, bch->nr);
addr = fc->addr + CHIP_WINDOW;
}
- while (cnt < count) {
- val = get_unaligned(ptr);
- outl(cpu_to_le32(val), addr);
- ptr++;
- cnt += 4;
+ if (fillempty) {
+ while (cnt < count) {
+ /* all bytes the same - no worry about endian */
+ outl(*ptr, addr);
+ cnt += 4;
+ }
+ } else {
+ while (cnt < count) {
+ val = get_unaligned(ptr);
+ outl(cpu_to_le32(val), addr);
+ ptr++;
+ cnt += 4;
+ }
}
- if (debug & DEBUG_HW_BFIFO) {
+ if ((debug & DEBUG_HW_BFIFO) && !fillempty) {
snprintf(fc->log, LOG_SIZE, "B%1d-send %s %d ",
bch->nr, fc->name, count);
print_hex_dump_bytes(fc->log, DUMP_PREFIX_OFFSET, p, count);
@@ -488,17 +517,17 @@ hdlc_fill_fifo(struct bchannel *bch)
static void
HDLC_irq_xpr(struct bchannel *bch)
{
- if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len)
+ if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len) {
hdlc_fill_fifo(bch);
- else {
- if (bch->tx_skb) {
- /* send confirm, on trans, free on hdlc. */
- if (test_bit(FLG_TRANSPARENT, &bch->Flags))
- confirm_Bsend(bch);
+ } else {
+ if (bch->tx_skb)
dev_kfree_skb(bch->tx_skb);
- }
- if (get_next_bframe(bch))
+ if (get_next_bframe(bch)) {
hdlc_fill_fifo(bch);
+ test_and_clear_bit(FLG_TX_EMPTY, &bch->Flags);
+ } else if (test_bit(FLG_TX_EMPTY, &bch->Flags)) {
+ hdlc_fill_fifo(bch);
+ }
}
}
@@ -506,13 +535,23 @@ static void
HDLC_irq(struct bchannel *bch, u32 stat)
{
struct fritzcard *fc = bch->hw;
- int len;
+ int len, fs;
+ u32 rmlMask;
struct hdlc_hw *hdlc;
hdlc = &fc->hdlc[(bch->nr - 1) & 1];
pr_debug("%s: ch%d stat %#x\n", fc->name, bch->nr, stat);
+ if (fc->type == AVM_FRITZ_PCIV2) {
+ rmlMask = HDLC_STAT_RML_MASK_V2;
+ fs = HDLC_FIFO_SIZE_V2;
+ } else {
+ rmlMask = HDLC_STAT_RML_MASK_V1;
+ fs = HDLC_FIFO_SIZE_V1;
+ }
if (stat & HDLC_INT_RPR) {
if (stat & HDLC_STAT_RDO) {
+ pr_warning("%s: ch%d stat %x RDO\n",
+ fc->name, bch->nr, stat);
hdlc->ctrl.sr.xml = 0;
hdlc->ctrl.sr.cmd |= HDLC_CMD_RRS;
write_ctrl(bch, 1);
@@ -521,21 +560,21 @@ HDLC_irq(struct bchannel *bch, u32 stat)
if (bch->rx_skb)
skb_trim(bch->rx_skb, 0);
} else {
- len = (stat & HDLC_STAT_RML_MASK) >> 8;
+ len = (stat & rmlMask) >> 8;
if (!len)
- len = 32;
+ len = fs;
hdlc_empty_fifo(bch, len);
if (!bch->rx_skb)
goto handle_tx;
- if ((stat & HDLC_STAT_RME) || test_bit(FLG_TRANSPARENT,
- &bch->Flags)) {
- if (((stat & HDLC_STAT_CRCVFRRAB) ==
- HDLC_STAT_CRCVFR) ||
- test_bit(FLG_TRANSPARENT, &bch->Flags)) {
- recv_Bchannel(bch, 0);
+ if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {
+ recv_Bchannel(bch, 0, false);
+ } else if (stat & HDLC_STAT_RME) {
+ if ((stat & HDLC_STAT_CRCVFRRAB) ==
+ HDLC_STAT_CRCVFR) {
+ recv_Bchannel(bch, 0, false);
} else {
- pr_debug("%s: got invalid frame\n",
- fc->name);
+ pr_warning("%s: got invalid frame\n",
+ fc->name);
skb_trim(bch->rx_skb, 0);
}
}
@@ -547,16 +586,13 @@ handle_tx:
* restart transmitting the whole frame on HDLC
* in transparent mode we send the next data
*/
- if (bch->tx_skb)
- pr_debug("%s: ch%d XDU len(%d) idx(%d) Flags(%lx)\n",
- fc->name, bch->nr, bch->tx_skb->len,
- bch->tx_idx, bch->Flags);
- else
- pr_debug("%s: ch%d XDU no tx_skb Flags(%lx)\n",
- fc->name, bch->nr, bch->Flags);
+ pr_warning("%s: ch%d stat %x XDU %s\n", fc->name, bch->nr,
+ stat, bch->tx_skb ? "tx_skb" : "no tx_skb");
if (bch->tx_skb && bch->tx_skb->len) {
if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
bch->tx_idx = 0;
+ } else if (test_bit(FLG_FILLEMPTY, &bch->Flags)) {
+ test_and_set_bit(FLG_TX_EMPTY, &bch->Flags);
}
hdlc->ctrl.sr.xml = 0;
hdlc->ctrl.sr.cmd |= HDLC_CMD_XRS;
@@ -659,22 +695,17 @@ avm_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
struct fritzcard *fc = bch->hw;
int ret = -EINVAL;
struct mISDNhead *hh = mISDN_HEAD_P(skb);
- u32 id;
- u_long flags;
+ unsigned long flags;
switch (hh->prim) {
case PH_DATA_REQ:
spin_lock_irqsave(&fc->lock, flags);
ret = bchannel_senddata(bch, skb);
if (ret > 0) { /* direct TX */
- id = hh->id; /* skb can be freed */
hdlc_fill_fifo(bch);
ret = 0;
- spin_unlock_irqrestore(&fc->lock, flags);
- if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
- queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
- } else
- spin_unlock_irqrestore(&fc->lock, flags);
+ }
+ spin_unlock_irqrestore(&fc->lock, flags);
return ret;
case PH_ACTIVATE_REQ:
spin_lock_irqsave(&fc->lock, flags);
@@ -783,7 +814,7 @@ init_card(struct fritzcard *fc)
inithdlc(fc);
enable_hwirq(fc);
/* RESET Receiver and Transmitter */
- if (AVM_FRITZ_PCIV2 == fc->type) {
+ if (fc->type == AVM_FRITZ_PCIV2) {
WriteISAC_V2(fc, ISACX_MASK, 0);
WriteISAC_V2(fc, ISACX_CMDRD, 0x41);
} else {
@@ -810,21 +841,7 @@ init_card(struct fritzcard *fc)
static int
channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
{
- int ret = 0;
- struct fritzcard *fc = bch->hw;
-
- switch (cq->op) {
- case MISDN_CTRL_GETOP:
- cq->op = 0;
- break;
- /* Nothing implemented yet */
- case MISDN_CTRL_FILL_EMPTY:
- default:
- pr_info("%s: %s unknown Op %x\n", fc->name, __func__, cq->op);
- ret = -EINVAL;
- break;
- }
- return ret;
+ return mISDN_ctrl_bchannel(bch, cq);
}
static int
@@ -839,14 +856,10 @@ avm_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
switch (cmd) {
case CLOSE_CHANNEL:
test_and_clear_bit(FLG_OPEN, &bch->Flags);
- if (test_bit(FLG_ACTIVE, &bch->Flags)) {
- spin_lock_irqsave(&fc->lock, flags);
- mISDN_freebchannel(bch);
- test_and_clear_bit(FLG_TX_BUSY, &bch->Flags);
- test_and_clear_bit(FLG_ACTIVE, &bch->Flags);
- modehdlc(bch, ISDN_P_NONE);
- spin_unlock_irqrestore(&fc->lock, flags);
- }
+ spin_lock_irqsave(&fc->lock, flags);
+ mISDN_freebchannel(bch);
+ modehdlc(bch, ISDN_P_NONE);
+ spin_unlock_irqrestore(&fc->lock, flags);
ch->protocol = ISDN_P_NONE;
ch->peer = NULL;
module_put(THIS_MODULE);
@@ -868,7 +881,7 @@ channel_ctrl(struct fritzcard *fc, struct mISDN_ctrl_req *cq)
switch (cq->op) {
case MISDN_CTRL_GETOP:
- cq->op = MISDN_CTRL_LOOP;
+ cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_L1_TIMER3;
break;
case MISDN_CTRL_LOOP:
/* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
@@ -878,6 +891,9 @@ channel_ctrl(struct fritzcard *fc, struct mISDN_ctrl_req *cq)
}
ret = fc->isac.ctrl(&fc->isac, HW_TESTLOOP, cq->channel);
break;
+ case MISDN_CTRL_L1_TIMER3:
+ ret = fc->isac.ctrl(&fc->isac, HW_TIMER3_VALUE, cq->p1);
+ break;
default:
pr_info("%s: %s unknown Op %x\n", fc->name, __func__, cq->op);
ret = -EINVAL;
@@ -898,7 +914,6 @@ open_bchannel(struct fritzcard *fc, struct channel_req *rq)
bch = &fc->bch[rq->adr.channel - 1];
if (test_and_set_bit(FLG_OPEN, &bch->Flags))
return -EBUSY; /* b-channel can be only open once */
- test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
bch->ch.protocol = rq->protocol;
rq->ch = &bch->ch;
return 0;
@@ -1021,6 +1036,7 @@ static int __devinit
setup_instance(struct fritzcard *card)
{
int i, err;
+ unsigned short minsize;
u_long flags;
snprintf(card->name, MISDN_MAX_IDLEN - 1, "AVM.%d", AVM_cnt + 1);
@@ -1040,7 +1056,11 @@ setup_instance(struct fritzcard *card)
for (i = 0; i < 2; i++) {
card->bch[i].nr = i + 1;
set_channelmap(i + 1, card->isac.dch.dev.channelmap);
- mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM);
+ if (AVM_FRITZ_PCIV2 == card->type)
+ minsize = HDLC_FIFO_SIZE_V2;
+ else
+ minsize = HDLC_FIFO_SIZE_V1;
+ mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM, minsize);
card->bch[i].hw = card;
card->bch[i].ch.send = avm_l2l1B;
card->bch[i].ch.ctrl = avm_bctrl;
diff --git a/drivers/isdn/hardware/mISDN/hfc_multi.h b/drivers/isdn/hardware/mISDN/hfc_multi.h
index b0588acbb47d..c601f880141e 100644
--- a/drivers/isdn/hardware/mISDN/hfc_multi.h
+++ b/drivers/isdn/hardware/mISDN/hfc_multi.h
@@ -205,18 +205,22 @@ struct hfc_multi {
u_int slots; /* number of PCM slots */
u_int leds; /* type of leds */
- u_int ledcount; /* used to animate leds */
u_long ledstate; /* save last state of leds */
int opticalsupport; /* has the e1 board */
/* an optical Interface */
- int dslot; /* channel # of d-channel (E1) default 16 */
+
+ u_int bmask[32]; /* bitmask of bchannels for port */
+ u_char dnum[32]; /* array of used dchannel numbers for port */
+ u_char created[32]; /* what port is created */
+ u_int activity_tx; /* if there is data TX / RX */
+ u_int activity_rx; /* bitmask according to port number */
+ /* (will be cleared after */
+ /* showing led-states) */
+ u_int flash[8]; /* counter for flashing 8 leds on activity */
u_long wdcount; /* every 500 ms we need to */
/* send the watchdog a signal */
u_char wdbyte; /* watchdog toggle byte */
- u_int activity[8]; /* if there is any action on this */
- /* port (will be cleared after */
- /* showing led-states) */
int e1_state; /* keep track of last state */
int e1_getclock; /* if sync is retrieved from interface */
int syncronized; /* keep track of existing sync interface */
@@ -233,7 +237,6 @@ struct hfc_multi {
* the bch->channel is equvalent to the hfc-channel
*/
struct hfc_chan chan[32];
- u_char created[8]; /* what port is created */
signed char slot_owner[256]; /* owner channel of slot */
};
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index 033223180b55..5e402cf2e795 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -103,14 +103,26 @@
* Omit this value, if all cards are interconnected or none is connected.
* If unsure, don't give this parameter.
*
- * dslot:
- * NOTE: only one dslot value must be given for every card.
- * Also this value must be given for non-E1 cards. If omitted, the E1
- * card has D-channel on time slot 16, which is default.
- * If 1..15 or 17..31, an alternate time slot is used for D-channel.
- * In this case, the application must be able to handle this.
- * If -1 is given, the D-channel is disabled and all 31 slots can be used
- * for B-channel. (only for specific applications)
+ * dmask and bmask:
+ * NOTE: One dmask value must be given for every HFC-E1 card.
+ * If omitted, the E1 card has D-channel on time slot 16, which is default.
+ * dmask is a 32 bit mask. The bit must be set for an alternate time slot.
+ * If multiple bits are set, multiple virtual card fragments are created.
+ * For each bit set, a bmask value must be given. Each bit on the bmask
+ * value stands for a B-channel. The bmask may not overlap with dmask or
+ * with other bmask values for that card.
+ * Example: dmask=0x00020002 bmask=0x0000fffc,0xfffc0000
+ * This will create one fragment with D-channel on slot 1 with
+ * B-channels on slots 2..15, and a second fragment with D-channel
+ * on slot 17 with B-channels on slot 18..31. Slot 16 is unused.
+ * If bit 0 is set (dmask=0x00000001) the D-channel is on slot 0 and will
+ * not function.
+ * Example: dmask=0x00000001 bmask=0xfffffffe
+ * This will create a port with all 31 usable timeslots as
+ * B-channels.
+ * If no bits are set on bmask, no B-channel is created for that fragment.
+ * Example: dmask=0xfffffffe bmask=0,0,0,0.... (31 0-values for bmask)
+ * This will create 31 ports with one D-channel only.
* If you don't know how to use it, you don't need it!
*
* iomode:
@@ -172,6 +184,7 @@
#define MAX_CARDS 8
#define MAX_PORTS (8 * MAX_CARDS)
+#define MAX_FRAGS (32 * MAX_CARDS)
static LIST_HEAD(HFClist);
static spinlock_t HFClock; /* global hfc list lock */
@@ -203,7 +216,8 @@ static int nt_t1_count[] = { 3840, 1920, 960, 480, 240, 120, 60, 30 };
static uint type[MAX_CARDS];
static int pcm[MAX_CARDS];
-static int dslot[MAX_CARDS];
+static uint dmask[MAX_CARDS];
+static uint bmask[MAX_FRAGS];
static uint iomode[MAX_CARDS];
static uint port[MAX_PORTS];
static uint debug;
@@ -218,7 +232,7 @@ static uint clockdelay_nt = CLKDEL_NT;
#define HWID_MINIP16 3
static uint hwid = HWID_NONE;
-static int HFC_cnt, Port_cnt, PCM_cnt = 99;
+static int HFC_cnt, E1_cnt, bmask_cnt, Port_cnt, PCM_cnt = 99;
MODULE_AUTHOR("Andreas Eversberg");
MODULE_LICENSE("GPL");
@@ -231,7 +245,8 @@ module_param(clockdelay_te, uint, S_IRUGO | S_IWUSR);
module_param(clockdelay_nt, uint, S_IRUGO | S_IWUSR);
module_param_array(type, uint, NULL, S_IRUGO | S_IWUSR);
module_param_array(pcm, int, NULL, S_IRUGO | S_IWUSR);
-module_param_array(dslot, int, NULL, S_IRUGO | S_IWUSR);
+module_param_array(dmask, uint, NULL, S_IRUGO | S_IWUSR);
+module_param_array(bmask, uint, NULL, S_IRUGO | S_IWUSR);
module_param_array(iomode, uint, NULL, S_IRUGO | S_IWUSR);
module_param_array(port, uint, NULL, S_IRUGO | S_IWUSR);
module_param(hwid, uint, S_IRUGO | S_IWUSR); /* The hardware ID */
@@ -1156,7 +1171,7 @@ init_chip(struct hfc_multi *hc)
hc->DTMFbase = 0x1000;
if (test_bit(HFC_CHIP_EXRAM_128, &hc->chip)) {
if (debug & DEBUG_HFCMULTI_INIT)
- printk(KERN_DEBUG "%s: changing to 128K extenal RAM\n",
+ printk(KERN_DEBUG "%s: changing to 128K external RAM\n",
__func__);
hc->hw.r_ctrl |= V_EXT_RAM;
hc->hw.r_ram_sz = 1;
@@ -1167,7 +1182,7 @@ init_chip(struct hfc_multi *hc)
}
if (test_bit(HFC_CHIP_EXRAM_512, &hc->chip)) {
if (debug & DEBUG_HFCMULTI_INIT)
- printk(KERN_DEBUG "%s: changing to 512K extenal RAM\n",
+ printk(KERN_DEBUG "%s: changing to 512K external RAM\n",
__func__);
hc->hw.r_ctrl |= V_EXT_RAM;
hc->hw.r_ram_sz = 2;
@@ -1607,40 +1622,46 @@ hfcmulti_leds(struct hfc_multi *hc)
struct dchannel *dch;
int led[4];
- hc->ledcount += poll;
- if (hc->ledcount > 4096) {
- hc->ledcount -= 4096;
- hc->ledstate = 0xAFFEAFFE;
- }
-
switch (hc->leds) {
case 1: /* HFC-E1 OEM */
- /* 2 red blinking: NT mode deactivate
- * 2 red steady: TE mode deactivate
- * left green: L1 active
- * left red: frame sync, but no L1
- * right green: L2 active
+ /* 2 red steady: LOS
+ * 1 red steady: L1 not active
+ * 2 green steady: L1 active
+ * 1st green flashing: activity on TX
+ * 2nd green flashing: activity on RX
*/
- if (hc->chan[hc->dslot].sync != 2) { /* no frame sync */
- if (hc->chan[hc->dslot].dch->dev.D.protocol
- != ISDN_P_NT_E1) {
- led[0] = 1;
+ led[0] = 0;
+ led[1] = 0;
+ led[2] = 0;
+ led[3] = 0;
+ dch = hc->chan[hc->dnum[0]].dch;
+ if (dch) {
+ if (hc->chan[hc->dnum[0]].los)
led[1] = 1;
- } else if (hc->ledcount >> 11) {
+ if (hc->e1_state != 1) {
led[0] = 1;
- led[1] = 1;
+ hc->flash[2] = 0;
+ hc->flash[3] = 0;
} else {
- led[0] = 0;
- led[1] = 0;
+ led[2] = 1;
+ led[3] = 1;
+ if (!hc->flash[2] && hc->activity_tx)
+ hc->flash[2] = poll;
+ if (!hc->flash[3] && hc->activity_rx)
+ hc->flash[3] = poll;
+ if (hc->flash[2] && hc->flash[2] < 1024)
+ led[2] = 0;
+ if (hc->flash[3] && hc->flash[3] < 1024)
+ led[3] = 0;
+ if (hc->flash[2] >= 2048)
+ hc->flash[2] = 0;
+ if (hc->flash[3] >= 2048)
+ hc->flash[3] = 0;
+ if (hc->flash[2])
+ hc->flash[2] += poll;
+ if (hc->flash[3])
+ hc->flash[3] += poll;
}
- led[2] = 0;
- led[3] = 0;
- } else { /* with frame sync */
- /* TODO make it work */
- led[0] = 0;
- led[1] = 0;
- led[2] = 0;
- led[3] = 1;
}
leds = (led[0] | (led[1]<<2) | (led[2]<<1) | (led[3]<<3))^0xF;
/* leds are inverted */
@@ -1651,9 +1672,9 @@ hfcmulti_leds(struct hfc_multi *hc)
break;
case 2: /* HFC-4S OEM */
- /* red blinking = PH_DEACTIVATE NT Mode
- * red steady = PH_DEACTIVATE TE Mode
- * green steady = PH_ACTIVATE
+ /* red steady: PH_DEACTIVATE
+ * green steady: PH_ACTIVATE
+ * green flashing: activity on TX
*/
for (i = 0; i < 4; i++) {
state = 0;
@@ -1669,17 +1690,20 @@ hfcmulti_leds(struct hfc_multi *hc)
if (state) {
if (state == active) {
led[i] = 1; /* led green */
- } else
- if (dch->dev.D.protocol == ISDN_P_TE_S0)
- /* TE mode: led red */
- led[i] = 2;
- else
- if (hc->ledcount >> 11)
- /* led red */
- led[i] = 2;
- else
- /* led off */
- led[i] = 0;
+ hc->activity_tx |= hc->activity_rx;
+ if (!hc->flash[i] &&
+ (hc->activity_tx & (1 << i)))
+ hc->flash[i] = poll;
+ if (hc->flash[i] && hc->flash[i] < 1024)
+ led[i] = 0; /* led off */
+ if (hc->flash[i] >= 2048)
+ hc->flash[i] = 0;
+ if (hc->flash[i])
+ hc->flash[i] += poll;
+ } else {
+ led[i] = 2; /* led red */
+ hc->flash[i] = 0;
+ }
} else
led[i] = 0; /* led off */
}
@@ -1712,9 +1736,9 @@ hfcmulti_leds(struct hfc_multi *hc)
break;
case 3: /* HFC 1S/2S Beronet */
- /* red blinking = PH_DEACTIVATE NT Mode
- * red steady = PH_DEACTIVATE TE Mode
- * green steady = PH_ACTIVATE
+ /* red steady: PH_DEACTIVATE
+ * green steady: PH_ACTIVATE
+ * green flashing: activity on TX
*/
for (i = 0; i < 2; i++) {
state = 0;
@@ -1730,22 +1754,23 @@ hfcmulti_leds(struct hfc_multi *hc)
if (state) {
if (state == active) {
led[i] = 1; /* led green */
- } else
- if (dch->dev.D.protocol == ISDN_P_TE_S0)
- /* TE mode: led red */
- led[i] = 2;
- else
- if (hc->ledcount >> 11)
- /* led red */
- led[i] = 2;
- else
- /* led off */
- led[i] = 0;
+ hc->activity_tx |= hc->activity_rx;
+ if (!hc->flash[i] &&
+ (hc->activity_tx & (1 << i)))
+ hc->flash[i] = poll;
+ if (hc->flash[i] < 1024)
+ led[i] = 0; /* led off */
+ if (hc->flash[i] >= 2048)
+ hc->flash[i] = 0;
+ if (hc->flash[i])
+ hc->flash[i] += poll;
+ } else {
+ led[i] = 2; /* led red */
+ hc->flash[i] = 0;
+ }
} else
led[i] = 0; /* led off */
}
-
-
leds = (led[0] > 0) | ((led[1] > 0) << 1) | ((led[0]&1) << 2)
| ((led[1]&1) << 3);
if (leds != (int)hc->ledstate) {
@@ -1757,8 +1782,11 @@ hfcmulti_leds(struct hfc_multi *hc)
}
break;
case 8: /* HFC 8S+ Beronet */
- lled = 0;
-
+ /* off: PH_DEACTIVATE
+ * steady: PH_ACTIVATE
+ * flashing: activity on TX
+ */
+ lled = 0xff; /* leds off */
for (i = 0; i < 8; i++) {
state = 0;
active = -1;
@@ -1772,14 +1800,20 @@ hfcmulti_leds(struct hfc_multi *hc)
}
if (state) {
if (state == active) {
- lled |= 0 << i;
+ lled &= ~(1 << i); /* led on */
+ hc->activity_tx |= hc->activity_rx;
+ if (!hc->flash[i] &&
+ (hc->activity_tx & (1 << i)))
+ hc->flash[i] = poll;
+ if (hc->flash[i] < 1024)
+ lled |= 1 << i; /* led off */
+ if (hc->flash[i] >= 2048)
+ hc->flash[i] = 0;
+ if (hc->flash[i])
+ hc->flash[i] += poll;
} else
- if (hc->ledcount >> 11)
- lled |= 0 << i;
- else
- lled |= 1 << i;
- } else
- lled |= 1 << i;
+ hc->flash[i] = 0;
+ }
}
leddw = lled << 24 | lled << 16 | lled << 8 | lled;
if (leddw != hc->ledstate) {
@@ -1794,6 +1828,8 @@ hfcmulti_leds(struct hfc_multi *hc)
}
break;
}
+ hc->activity_tx = 0;
+ hc->activity_rx = 0;
}
/*
* read dtmf coefficients
@@ -2093,7 +2129,8 @@ next_frame:
*txpending = 1;
/* show activity */
- hc->activity[hc->chan[ch].port] = 1;
+ if (dch)
+ hc->activity_tx |= 1 << hc->chan[ch].port;
/* fill fifo to what we have left */
ii = len;
@@ -2129,13 +2166,9 @@ next_frame:
HFC_wait_nodebug(hc);
}
- /* send confirm, since get_net_bframe will not do it with trans */
- if (bch && test_bit(FLG_TRANSPARENT, &bch->Flags))
- confirm_Bsend(bch);
-
- /* check for next frame */
dev_kfree_skb(*sp);
- if (bch && get_next_bframe(bch)) { /* hdlc is confirmed here */
+ /* check for next frame */
+ if (bch && get_next_bframe(bch)) {
len = (*sp)->len;
goto next_frame;
}
@@ -2163,24 +2196,20 @@ hfcmulti_rx(struct hfc_multi *hc, int ch)
int f1 = 0, f2 = 0; /* = 0, to make GCC happy */
int again = 0;
struct bchannel *bch;
- struct dchannel *dch;
+ struct dchannel *dch = NULL;
struct sk_buff *skb, **sp = NULL;
int maxlen;
bch = hc->chan[ch].bch;
- dch = hc->chan[ch].dch;
- if ((!dch) && (!bch))
- return;
- if (dch) {
+ if (bch) {
+ if (!test_bit(FLG_ACTIVE, &bch->Flags))
+ return;
+ } else if (hc->chan[ch].dch) {
+ dch = hc->chan[ch].dch;
if (!test_bit(FLG_ACTIVE, &dch->Flags))
return;
- sp = &dch->rx_skb;
- maxlen = dch->maxlen;
} else {
- if (!test_bit(FLG_ACTIVE, &bch->Flags))
- return;
- sp = &bch->rx_skb;
- maxlen = bch->maxlen;
+ return;
}
next_frame:
/* on first AND before getting next valid frame, R_FIFO must be written
@@ -2195,8 +2224,11 @@ next_frame:
HFC_wait_nodebug(hc);
/* ignore if rx is off BUT change fifo (above) to start pending TX */
- if (hc->chan[ch].rx_off)
+ if (hc->chan[ch].rx_off) {
+ if (bch)
+ bch->dropcnt += poll; /* not exact but fair enough */
return;
+ }
if (dch || test_bit(FLG_HDLC, &bch->Flags)) {
f1 = HFC_inb_nodebug(hc, A_F1);
@@ -2227,16 +2259,30 @@ next_frame:
if (Zsize <= 0)
return;
- if (*sp == NULL) {
- *sp = mI_alloc_skb(maxlen + 3, GFP_ATOMIC);
- if (*sp == NULL) {
- printk(KERN_DEBUG "%s: No mem for rx_skb\n",
- __func__);
+ if (bch) {
+ maxlen = bchannel_get_rxbuf(bch, Zsize);
+ if (maxlen < 0) {
+ pr_warning("card%d.B%d: No bufferspace for %d bytes\n",
+ hc->id + 1, bch->nr, Zsize);
return;
}
+ sp = &bch->rx_skb;
+ maxlen = bch->maxlen;
+ } else { /* Dchannel */
+ sp = &dch->rx_skb;
+ maxlen = dch->maxlen + 3;
+ if (*sp == NULL) {
+ *sp = mI_alloc_skb(maxlen, GFP_ATOMIC);
+ if (*sp == NULL) {
+ pr_warning("card%d: No mem for dch rx_skb\n",
+ hc->id + 1);
+ return;
+ }
+ }
}
/* show activity */
- hc->activity[hc->chan[ch].port] = 1;
+ if (dch)
+ hc->activity_rx |= 1 << hc->chan[ch].port;
/* empty fifo with what we have */
if (dch || test_bit(FLG_HDLC, &bch->Flags)) {
@@ -2247,7 +2293,7 @@ next_frame:
Zsize, z1, z2, (f1 == f2) ? "fragment" : "COMPLETE",
f1, f2, Zsize + (*sp)->len, again);
/* HDLC */
- if ((Zsize + (*sp)->len) > (maxlen + 3)) {
+ if ((Zsize + (*sp)->len) > maxlen) {
if (debug & DEBUG_HFCMULTI_FIFO)
printk(KERN_DEBUG
"%s(card %d): hdlc-frame too large.\n",
@@ -2309,7 +2355,7 @@ next_frame:
if (dch)
recv_Dchannel(dch);
else
- recv_Bchannel(bch, MISDN_ID_ANY);
+ recv_Bchannel(bch, MISDN_ID_ANY, false);
*sp = skb;
again++;
goto next_frame;
@@ -2317,32 +2363,14 @@ next_frame:
/* there is an incomplete frame */
} else {
/* transparent */
- if (Zsize > skb_tailroom(*sp))
- Zsize = skb_tailroom(*sp);
hc->read_fifo(hc, skb_put(*sp, Zsize), Zsize);
- if (((*sp)->len) < MISDN_COPY_SIZE) {
- skb = *sp;
- *sp = mI_alloc_skb(skb->len, GFP_ATOMIC);
- if (*sp) {
- memcpy(skb_put(*sp, skb->len),
- skb->data, skb->len);
- skb_trim(skb, 0);
- } else {
- printk(KERN_DEBUG "%s: No mem\n", __func__);
- *sp = skb;
- skb = NULL;
- }
- } else {
- skb = NULL;
- }
if (debug & DEBUG_HFCMULTI_FIFO)
printk(KERN_DEBUG
"%s(card %d): fifo(%d) reading %d bytes "
"(z1=%04x, z2=%04x) TRANS\n",
__func__, hc->id + 1, ch, Zsize, z1, z2);
/* only bch is transparent */
- recv_Bchannel(bch, hc->chan[ch].Zfill);
- *sp = skb;
+ recv_Bchannel(bch, hc->chan[ch].Zfill, false);
}
}
@@ -2430,55 +2458,55 @@ handle_timer_irq(struct hfc_multi *hc)
}
}
if (hc->ctype == HFC_TYPE_E1 && hc->created[0]) {
- dch = hc->chan[hc->dslot].dch;
- if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[hc->dslot].cfg)) {
- /* LOS */
- temp = HFC_inb_nodebug(hc, R_SYNC_STA) & V_SIG_LOS;
- if (!temp && hc->chan[hc->dslot].los)
+ dch = hc->chan[hc->dnum[0]].dch;
+ /* LOS */
+ temp = HFC_inb_nodebug(hc, R_SYNC_STA) & V_SIG_LOS;
+ hc->chan[hc->dnum[0]].los = temp;
+ if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[hc->dnum[0]].cfg)) {
+ if (!temp && hc->chan[hc->dnum[0]].los)
signal_state_up(dch, L1_SIGNAL_LOS_ON,
"LOS detected");
- if (temp && !hc->chan[hc->dslot].los)
+ if (temp && !hc->chan[hc->dnum[0]].los)
signal_state_up(dch, L1_SIGNAL_LOS_OFF,
"LOS gone");
- hc->chan[hc->dslot].los = temp;
}
- if (test_bit(HFC_CFG_REPORT_AIS, &hc->chan[hc->dslot].cfg)) {
+ if (test_bit(HFC_CFG_REPORT_AIS, &hc->chan[hc->dnum[0]].cfg)) {
/* AIS */
temp = HFC_inb_nodebug(hc, R_SYNC_STA) & V_AIS;
- if (!temp && hc->chan[hc->dslot].ais)
+ if (!temp && hc->chan[hc->dnum[0]].ais)
signal_state_up(dch, L1_SIGNAL_AIS_ON,
"AIS detected");
- if (temp && !hc->chan[hc->dslot].ais)
+ if (temp && !hc->chan[hc->dnum[0]].ais)
signal_state_up(dch, L1_SIGNAL_AIS_OFF,
"AIS gone");
- hc->chan[hc->dslot].ais = temp;
+ hc->chan[hc->dnum[0]].ais = temp;
}
- if (test_bit(HFC_CFG_REPORT_SLIP, &hc->chan[hc->dslot].cfg)) {
+ if (test_bit(HFC_CFG_REPORT_SLIP, &hc->chan[hc->dnum[0]].cfg)) {
/* SLIP */
temp = HFC_inb_nodebug(hc, R_SLIP) & V_FOSLIP_RX;
- if (!temp && hc->chan[hc->dslot].slip_rx)
+ if (!temp && hc->chan[hc->dnum[0]].slip_rx)
signal_state_up(dch, L1_SIGNAL_SLIP_RX,
" bit SLIP detected RX");
- hc->chan[hc->dslot].slip_rx = temp;
+ hc->chan[hc->dnum[0]].slip_rx = temp;
temp = HFC_inb_nodebug(hc, R_SLIP) & V_FOSLIP_TX;
- if (!temp && hc->chan[hc->dslot].slip_tx)
+ if (!temp && hc->chan[hc->dnum[0]].slip_tx)
signal_state_up(dch, L1_SIGNAL_SLIP_TX,
" bit SLIP detected TX");
- hc->chan[hc->dslot].slip_tx = temp;
+ hc->chan[hc->dnum[0]].slip_tx = temp;
}
- if (test_bit(HFC_CFG_REPORT_RDI, &hc->chan[hc->dslot].cfg)) {
+ if (test_bit(HFC_CFG_REPORT_RDI, &hc->chan[hc->dnum[0]].cfg)) {
/* RDI */
temp = HFC_inb_nodebug(hc, R_RX_SL0_0) & V_A;
- if (!temp && hc->chan[hc->dslot].rdi)
+ if (!temp && hc->chan[hc->dnum[0]].rdi)
signal_state_up(dch, L1_SIGNAL_RDI_ON,
"RDI detected");
- if (temp && !hc->chan[hc->dslot].rdi)
+ if (temp && !hc->chan[hc->dnum[0]].rdi)
signal_state_up(dch, L1_SIGNAL_RDI_OFF,
"RDI gone");
- hc->chan[hc->dslot].rdi = temp;
+ hc->chan[hc->dnum[0]].rdi = temp;
}
temp = HFC_inb_nodebug(hc, R_JATT_DIR);
- switch (hc->chan[hc->dslot].sync) {
+ switch (hc->chan[hc->dnum[0]].sync) {
case 0:
if ((temp & 0x60) == 0x60) {
if (debug & DEBUG_HFCMULTI_SYNC)
@@ -2487,10 +2515,10 @@ handle_timer_irq(struct hfc_multi *hc)
"in clock sync\n",
__func__, hc->id);
HFC_outb(hc, R_RX_OFF,
- hc->chan[hc->dslot].jitter | V_RX_INIT);
+ hc->chan[hc->dnum[0]].jitter | V_RX_INIT);
HFC_outb(hc, R_TX_OFF,
- hc->chan[hc->dslot].jitter | V_RX_INIT);
- hc->chan[hc->dslot].sync = 1;
+ hc->chan[hc->dnum[0]].jitter | V_RX_INIT);
+ hc->chan[hc->dnum[0]].sync = 1;
goto check_framesync;
}
break;
@@ -2501,7 +2529,7 @@ handle_timer_irq(struct hfc_multi *hc)
"%s: (id=%d) E1 "
"lost clock sync\n",
__func__, hc->id);
- hc->chan[hc->dslot].sync = 0;
+ hc->chan[hc->dnum[0]].sync = 0;
break;
}
check_framesync:
@@ -2512,7 +2540,7 @@ handle_timer_irq(struct hfc_multi *hc)
"%s: (id=%d) E1 "
"now in frame sync\n",
__func__, hc->id);
- hc->chan[hc->dslot].sync = 2;
+ hc->chan[hc->dnum[0]].sync = 2;
}
break;
case 2:
@@ -2522,7 +2550,7 @@ handle_timer_irq(struct hfc_multi *hc)
"%s: (id=%d) E1 lost "
"clock & frame sync\n",
__func__, hc->id);
- hc->chan[hc->dslot].sync = 0;
+ hc->chan[hc->dnum[0]].sync = 0;
break;
}
temp = HFC_inb_nodebug(hc, R_SYNC_STA);
@@ -2532,7 +2560,7 @@ handle_timer_irq(struct hfc_multi *hc)
"%s: (id=%d) E1 "
"lost frame sync\n",
__func__, hc->id);
- hc->chan[hc->dslot].sync = 1;
+ hc->chan[hc->dnum[0]].sync = 1;
}
break;
}
@@ -2673,7 +2701,7 @@ hfcmulti_interrupt(int intno, void *dev_id)
int i;
void __iomem *plx_acc;
u_short wval;
- u_char e1_syncsta, temp;
+ u_char e1_syncsta, temp, temp2;
u_long flags;
if (!hc) {
@@ -2748,7 +2776,7 @@ hfcmulti_interrupt(int intno, void *dev_id)
if (r_irq_misc & V_STA_IRQ) {
if (hc->ctype == HFC_TYPE_E1) {
/* state machine */
- dch = hc->chan[hc->dslot].dch;
+ dch = hc->chan[hc->dnum[0]].dch;
e1_syncsta = HFC_inb_nodebug(hc, R_SYNC_STA);
if (test_bit(HFC_CHIP_PLXSD, &hc->chip)
&& hc->e1_getclock) {
@@ -2758,23 +2786,26 @@ hfcmulti_interrupt(int intno, void *dev_id)
hc->syncronized = 0;
}
/* undocumented: status changes during read */
- dch->state = HFC_inb_nodebug(hc, R_E1_RD_STA);
- while (dch->state != (temp =
+ temp = HFC_inb_nodebug(hc, R_E1_RD_STA);
+ while (temp != (temp2 =
HFC_inb_nodebug(hc, R_E1_RD_STA))) {
if (debug & DEBUG_HFCMULTI_STATE)
printk(KERN_DEBUG "%s: reread "
"STATE because %d!=%d\n",
- __func__, temp,
- dch->state);
- dch->state = temp; /* repeat */
+ __func__, temp, temp2);
+ temp = temp2; /* repeat */
}
- dch->state = HFC_inb_nodebug(hc, R_E1_RD_STA)
- & 0x7;
- schedule_event(dch, FLG_PHCHANGE);
+ /* broadcast state change to all fragments */
if (debug & DEBUG_HFCMULTI_STATE)
printk(KERN_DEBUG
"%s: E1 (id=%d) newstate %x\n",
- __func__, hc->id, dch->state);
+ __func__, hc->id, temp & 0x7);
+ for (i = 0; i < hc->ports; i++) {
+ dch = hc->chan[hc->dnum[i]].dch;
+ dch->state = temp & 0x7;
+ schedule_event(dch, FLG_PHCHANGE);
+ }
+
if (test_bit(HFC_CHIP_PLXSD, &hc->chip))
plxsd_checksync(hc, 0);
}
@@ -3018,8 +3049,10 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx,
HFC_outb(hc, A_CON_HDLC, 0x20 | V_HDLC_TRP | V_IFF);
HFC_outb(hc, A_SUBCH_CFG, 0);
HFC_outb(hc, A_IRQ_MSK, 0);
- HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
- HFC_wait(hc);
+ if (hc->chan[ch].protocol != protocol) {
+ HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
+ HFC_wait(hc);
+ }
HFC_outb(hc, R_SLOT, ((((ch / 4) * 8) +
((ch % 4) * 4) + 1) << 1) | 1);
HFC_outb(hc, A_SL_CFG, 0x80 | 0x20 | (ch << 1) | 1);
@@ -3039,8 +3072,10 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx,
HFC_outb(hc, A_CON_HDLC, 0x20 | V_HDLC_TRP | V_IFF);
HFC_outb(hc, A_SUBCH_CFG, 0);
HFC_outb(hc, A_IRQ_MSK, 0);
- HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
- HFC_wait(hc);
+ if (hc->chan[ch].protocol != protocol) {
+ HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
+ HFC_wait(hc);
+ }
/* tx silence */
HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, hc->silence);
HFC_outb(hc, R_SLOT, (((ch / 4) * 8) +
@@ -3059,8 +3094,10 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx,
V_HDLC_TRP | V_IFF);
HFC_outb(hc, A_SUBCH_CFG, 0);
HFC_outb(hc, A_IRQ_MSK, 0);
- HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
- HFC_wait(hc);
+ if (hc->chan[ch].protocol != protocol) {
+ HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
+ HFC_wait(hc);
+ }
/* tx silence */
HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, hc->silence);
/* enable RX fifo */
@@ -3075,8 +3112,10 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx,
V_HDLC_TRP);
HFC_outb(hc, A_SUBCH_CFG, 0);
HFC_outb(hc, A_IRQ_MSK, 0);
- HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
- HFC_wait(hc);
+ if (hc->chan[ch].protocol != protocol) {
+ HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
+ HFC_wait(hc);
+ }
}
if (hc->ctype != HFC_TYPE_E1) {
hc->hw.a_st_ctrl0[hc->chan[ch].port] |=
@@ -3433,8 +3472,7 @@ handle_bmsg(struct mISDNchannel *ch, struct sk_buff *skb)
struct hfc_multi *hc = bch->hw;
int ret = -EINVAL;
struct mISDNhead *hh = mISDN_HEAD_P(skb);
- unsigned int id;
- u_long flags;
+ unsigned long flags;
switch (hh->prim) {
case PH_DATA_REQ:
@@ -3443,19 +3481,13 @@ handle_bmsg(struct mISDNchannel *ch, struct sk_buff *skb)
spin_lock_irqsave(&hc->lock, flags);
ret = bchannel_senddata(bch, skb);
if (ret > 0) { /* direct TX */
- id = hh->id; /* skb can be freed */
hfcmulti_tx(hc, bch->slot);
ret = 0;
/* start fifo */
HFC_outb_nodebug(hc, R_FIFO, 0);
HFC_wait_nodebug(hc);
- if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) {
- spin_unlock_irqrestore(&hc->lock, flags);
- queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
- } else
- spin_unlock_irqrestore(&hc->lock, flags);
- } else
- spin_unlock_irqrestore(&hc->lock, flags);
+ }
+ spin_unlock_irqrestore(&hc->lock, flags);
return ret;
case PH_ACTIVATE_REQ:
if (debug & DEBUG_HFCMULTI_MSG)
@@ -3545,10 +3577,11 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
switch (cq->op) {
case MISDN_CTRL_GETOP:
- cq->op = MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP
- | MISDN_CTRL_RX_OFF | MISDN_CTRL_FILL_EMPTY;
+ ret = mISDN_ctrl_bchannel(bch, cq);
+ cq->op |= MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP;
break;
case MISDN_CTRL_RX_OFF: /* turn off / on rx stream */
+ ret = mISDN_ctrl_bchannel(bch, cq);
hc->chan[bch->slot].rx_off = !!cq->p1;
if (!hc->chan[bch->slot].rx_off) {
/* reset fifo on rx on */
@@ -3561,11 +3594,10 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
printk(KERN_DEBUG "%s: RX_OFF request (nr=%d off=%d)\n",
__func__, bch->nr, hc->chan[bch->slot].rx_off);
break;
- case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */
- test_and_set_bit(FLG_FILLEMPTY, &bch->Flags);
- if (debug & DEBUG_HFCMULTI_MSG)
- printk(KERN_DEBUG "%s: FILL_EMPTY request (nr=%d "
- "off=%d)\n", __func__, bch->nr, !!cq->p1);
+ case MISDN_CTRL_FILL_EMPTY:
+ ret = mISDN_ctrl_bchannel(bch, cq);
+ hc->silence = bch->fill[0];
+ memset(hc->silence_data, hc->silence, sizeof(hc->silence_data));
break;
case MISDN_CTRL_HW_FEATURES: /* fill features structure */
if (debug & DEBUG_HFCMULTI_MSG)
@@ -3654,9 +3686,7 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
ret = -EINVAL;
break;
default:
- printk(KERN_WARNING "%s: unknown Op %x\n",
- __func__, cq->op);
- ret = -EINVAL;
+ ret = mISDN_ctrl_bchannel(bch, cq);
break;
}
return ret;
@@ -3676,8 +3706,7 @@ hfcm_bctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
switch (cmd) {
case CLOSE_CHANNEL:
test_and_clear_bit(FLG_OPEN, &bch->Flags);
- if (test_bit(FLG_ACTIVE, &bch->Flags))
- deactivate_bchannel(bch); /* locked there */
+ deactivate_bchannel(bch); /* locked there */
ch->protocol = ISDN_P_NONE;
ch->peer = NULL;
module_put(THIS_MODULE);
@@ -3839,31 +3868,37 @@ hfcmulti_initmode(struct dchannel *dch)
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG "%s: entered\n", __func__);
+ i = dch->slot;
+ pt = hc->chan[i].port;
if (hc->ctype == HFC_TYPE_E1) {
- hc->chan[hc->dslot].slot_tx = -1;
- hc->chan[hc->dslot].slot_rx = -1;
- hc->chan[hc->dslot].conf = -1;
- if (hc->dslot) {
- mode_hfcmulti(hc, hc->dslot, dch->dev.D.protocol,
+ /* E1 */
+ hc->chan[hc->dnum[pt]].slot_tx = -1;
+ hc->chan[hc->dnum[pt]].slot_rx = -1;
+ hc->chan[hc->dnum[pt]].conf = -1;
+ if (hc->dnum[pt]) {
+ mode_hfcmulti(hc, dch->slot, dch->dev.D.protocol,
-1, 0, -1, 0);
dch->timer.function = (void *) hfcmulti_dbusy_timer;
dch->timer.data = (long) dch;
init_timer(&dch->timer);
}
for (i = 1; i <= 31; i++) {
- if (i == hc->dslot)
+ if (!((1 << i) & hc->bmask[pt])) /* skip unused chan */
continue;
hc->chan[i].slot_tx = -1;
hc->chan[i].slot_rx = -1;
hc->chan[i].conf = -1;
mode_hfcmulti(hc, i, ISDN_P_NONE, -1, 0, -1, 0);
}
- /* E1 */
- if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[hc->dslot].cfg)) {
+ }
+ if (hc->ctype == HFC_TYPE_E1 && pt == 0) {
+ /* E1, port 0 */
+ dch = hc->chan[hc->dnum[0]].dch;
+ if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[hc->dnum[0]].cfg)) {
HFC_outb(hc, R_LOS0, 255); /* 2 ms */
HFC_outb(hc, R_LOS1, 255); /* 512 ms */
}
- if (test_bit(HFC_CFG_OPTICAL, &hc->chan[hc->dslot].cfg)) {
+ if (test_bit(HFC_CFG_OPTICAL, &hc->chan[hc->dnum[0]].cfg)) {
HFC_outb(hc, R_RX0, 0);
hc->hw.r_tx0 = 0 | V_OUT_EN;
} else {
@@ -3876,12 +3911,12 @@ hfcmulti_initmode(struct dchannel *dch)
HFC_outb(hc, R_TX_FR0, 0x00);
HFC_outb(hc, R_TX_FR1, 0xf8);
- if (test_bit(HFC_CFG_CRC4, &hc->chan[hc->dslot].cfg))
+ if (test_bit(HFC_CFG_CRC4, &hc->chan[hc->dnum[0]].cfg))
HFC_outb(hc, R_TX_FR2, V_TX_MF | V_TX_E | V_NEG_E);
HFC_outb(hc, R_RX_FR0, V_AUTO_RESYNC | V_AUTO_RECO | 0);
- if (test_bit(HFC_CFG_CRC4, &hc->chan[hc->dslot].cfg))
+ if (test_bit(HFC_CFG_CRC4, &hc->chan[hc->dnum[0]].cfg))
HFC_outb(hc, R_RX_FR1, V_RX_MF | V_RX_MF_SYNC);
if (dch->dev.D.protocol == ISDN_P_NT_E1) {
@@ -3944,13 +3979,14 @@ hfcmulti_initmode(struct dchannel *dch)
hc->syncronized = 0;
plxsd_checksync(hc, 0);
}
- } else {
- i = dch->slot;
+ }
+ if (hc->ctype != HFC_TYPE_E1) {
+ /* ST */
hc->chan[i].slot_tx = -1;
hc->chan[i].slot_rx = -1;
hc->chan[i].conf = -1;
mode_hfcmulti(hc, i, dch->dev.D.protocol, -1, 0, -1, 0);
- dch->timer.function = (void *)hfcmulti_dbusy_timer;
+ dch->timer.function = (void *) hfcmulti_dbusy_timer;
dch->timer.data = (long) dch;
init_timer(&dch->timer);
hc->chan[i - 2].slot_tx = -1;
@@ -3961,8 +3997,6 @@ hfcmulti_initmode(struct dchannel *dch)
hc->chan[i - 1].slot_rx = -1;
hc->chan[i - 1].conf = -1;
mode_hfcmulti(hc, i - 1, ISDN_P_NONE, -1, 0, -1, 0);
- /* ST */
- pt = hc->chan[i].port;
/* select interface */
HFC_outb(hc, R_ST_SEL, pt);
/* undocumented: delay after R_ST_SEL */
@@ -4054,14 +4088,9 @@ open_dchannel(struct hfc_multi *hc, struct dchannel *dch,
hfcmulti_initmode(dch);
spin_unlock_irqrestore(&hc->lock, flags);
}
-
- if (((rq->protocol == ISDN_P_NT_S0) && (dch->state == 3)) ||
- ((rq->protocol == ISDN_P_TE_S0) && (dch->state == 7)) ||
- ((rq->protocol == ISDN_P_NT_E1) && (dch->state == 1)) ||
- ((rq->protocol == ISDN_P_TE_E1) && (dch->state == 1))) {
+ if (test_bit(FLG_ACTIVE, &dch->Flags))
_queue_data(&dch->dev.D, PH_ACTIVATE_IND, MISDN_ID_ANY,
0, NULL, GFP_KERNEL);
- }
rq->ch = &dch->dev.D;
if (!try_module_get(THIS_MODULE))
printk(KERN_WARNING "%s:cannot get module\n", __func__);
@@ -4091,7 +4120,6 @@ open_bchannel(struct hfc_multi *hc, struct dchannel *dch,
}
if (test_and_set_bit(FLG_OPEN, &bch->Flags))
return -EBUSY; /* b-channel can be only open once */
- test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
bch->ch.protocol = rq->protocol;
hc->chan[ch].rx_off = 0;
rq->ch = &bch->ch;
@@ -4112,7 +4140,7 @@ channel_dctrl(struct dchannel *dch, struct mISDN_ctrl_req *cq)
switch (cq->op) {
case MISDN_CTRL_GETOP:
- cq->op = MISDN_CTRL_HFC_OP;
+ cq->op = MISDN_CTRL_HFC_OP | MISDN_CTRL_L1_TIMER3;
break;
case MISDN_CTRL_HFC_WD_INIT: /* init the watchdog */
wd_cnt = cq->p1 & 0xf;
@@ -4142,6 +4170,9 @@ channel_dctrl(struct dchannel *dch, struct mISDN_ctrl_req *cq)
__func__);
HFC_outb(hc, R_BERT_WD_MD, hc->hw.r_bert_wd_md | V_WD_RES);
break;
+ case MISDN_CTRL_L1_TIMER3:
+ ret = l1_event(dch->l1, HW_TIMER3_VALUE | (cq->p1 & 0xff));
+ break;
default:
printk(KERN_WARNING "%s: unknown Op %x\n",
__func__, cq->op);
@@ -4545,6 +4576,8 @@ release_port(struct hfc_multi *hc, struct dchannel *dch)
}
/* free channels */
for (i = 0; i <= 31; i++) {
+ if (!((1 << i) & hc->bmask[pt])) /* skip unused chan */
+ continue;
if (hc->chan[i].bch) {
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG
@@ -4600,7 +4633,8 @@ release_port(struct hfc_multi *hc, struct dchannel *dch)
spin_unlock_irqrestore(&hc->lock, flags);
if (debug & DEBUG_HFCMULTI_INIT)
- printk(KERN_DEBUG "%s: free port %d channel D\n", __func__, pt);
+ printk(KERN_DEBUG "%s: free port %d channel D(%d)\n", __func__,
+ pt+1, ci);
mISDN_freedchannel(dch);
kfree(dch);
@@ -4622,15 +4656,19 @@ release_card(struct hfc_multi *hc)
if (hc->iclock)
mISDN_unregister_clock(hc->iclock);
- /* disable irq */
+ /* disable and free irq */
spin_lock_irqsave(&hc->lock, flags);
disable_hwirq(hc);
spin_unlock_irqrestore(&hc->lock, flags);
udelay(1000);
+ if (hc->irq) {
+ if (debug & DEBUG_HFCMULTI_INIT)
+ printk(KERN_DEBUG "%s: free irq %d (hc=%p)\n",
+ __func__, hc->irq, hc);
+ free_irq(hc->irq, hc);
+ hc->irq = 0;
- /* dimm leds */
- if (hc->leds)
- hfcmulti_leds(hc);
+ }
/* disable D-channels & B-channels */
if (debug & DEBUG_HFCMULTI_INIT)
@@ -4641,15 +4679,11 @@ release_card(struct hfc_multi *hc)
release_port(hc, hc->chan[ch].dch);
}
- /* release hardware & irq */
- if (hc->irq) {
- if (debug & DEBUG_HFCMULTI_INIT)
- printk(KERN_DEBUG "%s: free irq %d\n",
- __func__, hc->irq);
- free_irq(hc->irq, hc);
- hc->irq = 0;
+ /* dimm leds */
+ if (hc->leds)
+ hfcmulti_leds(hc);
- }
+ /* release hardware */
release_io_hfcmulti(hc);
if (debug & DEBUG_HFCMULTI_INIT)
@@ -4667,61 +4701,9 @@ release_card(struct hfc_multi *hc)
__func__);
}
-static int
-init_e1_port(struct hfc_multi *hc, struct hm_map *m)
+static void
+init_e1_port_hw(struct hfc_multi *hc, struct hm_map *m)
{
- struct dchannel *dch;
- struct bchannel *bch;
- int ch, ret = 0;
- char name[MISDN_MAX_IDLEN];
-
- dch = kzalloc(sizeof(struct dchannel), GFP_KERNEL);
- if (!dch)
- return -ENOMEM;
- dch->debug = debug;
- mISDN_initdchannel(dch, MAX_DFRAME_LEN_L1, ph_state_change);
- dch->hw = hc;
- dch->dev.Dprotocols = (1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1);
- dch->dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) |
- (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK));
- dch->dev.D.send = handle_dmsg;
- dch->dev.D.ctrl = hfcm_dctrl;
- dch->dev.nrbchan = (hc->dslot) ? 30 : 31;
- dch->slot = hc->dslot;
- hc->chan[hc->dslot].dch = dch;
- hc->chan[hc->dslot].port = 0;
- hc->chan[hc->dslot].nt_timer = -1;
- for (ch = 1; ch <= 31; ch++) {
- if (ch == hc->dslot) /* skip dchannel */
- continue;
- bch = kzalloc(sizeof(struct bchannel), GFP_KERNEL);
- if (!bch) {
- printk(KERN_ERR "%s: no memory for bchannel\n",
- __func__);
- ret = -ENOMEM;
- goto free_chan;
- }
- hc->chan[ch].coeff = kzalloc(512, GFP_KERNEL);
- if (!hc->chan[ch].coeff) {
- printk(KERN_ERR "%s: no memory for coeffs\n",
- __func__);
- ret = -ENOMEM;
- kfree(bch);
- goto free_chan;
- }
- bch->nr = ch;
- bch->slot = ch;
- bch->debug = debug;
- mISDN_initbchannel(bch, MAX_DATA_MEM);
- bch->hw = hc;
- bch->ch.send = handle_bmsg;
- bch->ch.ctrl = hfcm_bctrl;
- bch->ch.nr = ch;
- list_add(&bch->ch.list, &dch->dev.bchannels);
- hc->chan[ch].bch = bch;
- hc->chan[ch].port = 0;
- set_channelmap(bch->nr, dch->dev.channelmap);
- }
/* set optical line type */
if (port[Port_cnt] & 0x001) {
if (!m->opticalsupport) {
@@ -4737,7 +4719,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m)
__func__,
HFC_cnt + 1, 1);
test_and_set_bit(HFC_CFG_OPTICAL,
- &hc->chan[hc->dslot].cfg);
+ &hc->chan[hc->dnum[0]].cfg);
}
}
/* set LOS report */
@@ -4747,7 +4729,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m)
"LOS report: card(%d) port(%d)\n",
__func__, HFC_cnt + 1, 1);
test_and_set_bit(HFC_CFG_REPORT_LOS,
- &hc->chan[hc->dslot].cfg);
+ &hc->chan[hc->dnum[0]].cfg);
}
/* set AIS report */
if (port[Port_cnt] & 0x008) {
@@ -4756,7 +4738,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m)
"AIS report: card(%d) port(%d)\n",
__func__, HFC_cnt + 1, 1);
test_and_set_bit(HFC_CFG_REPORT_AIS,
- &hc->chan[hc->dslot].cfg);
+ &hc->chan[hc->dnum[0]].cfg);
}
/* set SLIP report */
if (port[Port_cnt] & 0x010) {
@@ -4766,7 +4748,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m)
"card(%d) port(%d)\n",
__func__, HFC_cnt + 1, 1);
test_and_set_bit(HFC_CFG_REPORT_SLIP,
- &hc->chan[hc->dslot].cfg);
+ &hc->chan[hc->dnum[0]].cfg);
}
/* set RDI report */
if (port[Port_cnt] & 0x020) {
@@ -4776,7 +4758,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m)
"card(%d) port(%d)\n",
__func__, HFC_cnt + 1, 1);
test_and_set_bit(HFC_CFG_REPORT_RDI,
- &hc->chan[hc->dslot].cfg);
+ &hc->chan[hc->dnum[0]].cfg);
}
/* set CRC-4 Mode */
if (!(port[Port_cnt] & 0x100)) {
@@ -4785,7 +4767,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m)
" card(%d) port(%d)\n",
__func__, HFC_cnt + 1, 1);
test_and_set_bit(HFC_CFG_CRC4,
- &hc->chan[hc->dslot].cfg);
+ &hc->chan[hc->dnum[0]].cfg);
} else {
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG "%s: PORT turn off CRC4"
@@ -4817,20 +4799,85 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m)
}
/* set elastic jitter buffer */
if (port[Port_cnt] & 0x3000) {
- hc->chan[hc->dslot].jitter = (port[Port_cnt]>>12) & 0x3;
+ hc->chan[hc->dnum[0]].jitter = (port[Port_cnt]>>12) & 0x3;
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG
"%s: PORT set elastic "
"buffer to %d: card(%d) port(%d)\n",
- __func__, hc->chan[hc->dslot].jitter,
+ __func__, hc->chan[hc->dnum[0]].jitter,
HFC_cnt + 1, 1);
} else
- hc->chan[hc->dslot].jitter = 2; /* default */
- snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-e1.%d", HFC_cnt + 1);
+ hc->chan[hc->dnum[0]].jitter = 2; /* default */
+}
+
+static int
+init_e1_port(struct hfc_multi *hc, struct hm_map *m, int pt)
+{
+ struct dchannel *dch;
+ struct bchannel *bch;
+ int ch, ret = 0;
+ char name[MISDN_MAX_IDLEN];
+ int bcount = 0;
+
+ dch = kzalloc(sizeof(struct dchannel), GFP_KERNEL);
+ if (!dch)
+ return -ENOMEM;
+ dch->debug = debug;
+ mISDN_initdchannel(dch, MAX_DFRAME_LEN_L1, ph_state_change);
+ dch->hw = hc;
+ dch->dev.Dprotocols = (1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1);
+ dch->dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) |
+ (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK));
+ dch->dev.D.send = handle_dmsg;
+ dch->dev.D.ctrl = hfcm_dctrl;
+ dch->slot = hc->dnum[pt];
+ hc->chan[hc->dnum[pt]].dch = dch;
+ hc->chan[hc->dnum[pt]].port = pt;
+ hc->chan[hc->dnum[pt]].nt_timer = -1;
+ for (ch = 1; ch <= 31; ch++) {
+ if (!((1 << ch) & hc->bmask[pt])) /* skip unused channel */
+ continue;
+ bch = kzalloc(sizeof(struct bchannel), GFP_KERNEL);
+ if (!bch) {
+ printk(KERN_ERR "%s: no memory for bchannel\n",
+ __func__);
+ ret = -ENOMEM;
+ goto free_chan;
+ }
+ hc->chan[ch].coeff = kzalloc(512, GFP_KERNEL);
+ if (!hc->chan[ch].coeff) {
+ printk(KERN_ERR "%s: no memory for coeffs\n",
+ __func__);
+ ret = -ENOMEM;
+ kfree(bch);
+ goto free_chan;
+ }
+ bch->nr = ch;
+ bch->slot = ch;
+ bch->debug = debug;
+ mISDN_initbchannel(bch, MAX_DATA_MEM, poll >> 1);
+ bch->hw = hc;
+ bch->ch.send = handle_bmsg;
+ bch->ch.ctrl = hfcm_bctrl;
+ bch->ch.nr = ch;
+ list_add(&bch->ch.list, &dch->dev.bchannels);
+ hc->chan[ch].bch = bch;
+ hc->chan[ch].port = pt;
+ set_channelmap(bch->nr, dch->dev.channelmap);
+ bcount++;
+ }
+ dch->dev.nrbchan = bcount;
+ if (pt == 0)
+ init_e1_port_hw(hc, m);
+ if (hc->ports > 1)
+ snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-e1.%d-%d",
+ HFC_cnt + 1, pt+1);
+ else
+ snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-e1.%d", HFC_cnt + 1);
ret = mISDN_register_device(&dch->dev, &hc->pci_dev->dev, name);
if (ret)
goto free_chan;
- hc->created[0] = 1;
+ hc->created[pt] = 1;
return ret;
free_chan:
release_port(hc, dch);
@@ -4881,7 +4928,7 @@ init_multi_port(struct hfc_multi *hc, int pt)
bch->nr = ch + 1;
bch->slot = i + ch;
bch->debug = debug;
- mISDN_initbchannel(bch, MAX_DATA_MEM);
+ mISDN_initbchannel(bch, MAX_DATA_MEM, poll >> 1);
bch->hw = hc;
bch->ch.send = handle_bmsg;
bch->ch.ctrl = hfcm_bctrl;
@@ -4963,7 +5010,8 @@ hfcmulti_init(struct hm_map *m, struct pci_dev *pdev,
struct hfc_multi *hc;
u_long flags;
u_char dips = 0, pmj = 0; /* dip settings, port mode Jumpers */
- int i;
+ int i, ch;
+ u_int maskcheck;
if (HFC_cnt >= MAX_CARDS) {
printk(KERN_ERR "too many cards (max=%d).\n",
@@ -4997,18 +5045,36 @@ hfcmulti_init(struct hm_map *m, struct pci_dev *pdev,
hc->id = HFC_cnt;
hc->pcm = pcm[HFC_cnt];
hc->io_mode = iomode[HFC_cnt];
- if (dslot[HFC_cnt] < 0 && hc->ctype == HFC_TYPE_E1) {
- hc->dslot = 0;
- printk(KERN_INFO "HFC-E1 card has disabled D-channel, but "
- "31 B-channels\n");
- }
- if (dslot[HFC_cnt] > 0 && dslot[HFC_cnt] < 32
- && hc->ctype == HFC_TYPE_E1) {
- hc->dslot = dslot[HFC_cnt];
- printk(KERN_INFO "HFC-E1 card has alternating D-channel on "
- "time slot %d\n", dslot[HFC_cnt]);
- } else
- hc->dslot = 16;
+ if (hc->ctype == HFC_TYPE_E1 && dmask[E1_cnt]) {
+ /* fragment card */
+ pt = 0;
+ maskcheck = 0;
+ for (ch = 0; ch <= 31; ch++) {
+ if (!((1 << ch) & dmask[E1_cnt]))
+ continue;
+ hc->dnum[pt] = ch;
+ hc->bmask[pt] = bmask[bmask_cnt++];
+ if ((maskcheck & hc->bmask[pt])
+ || (dmask[E1_cnt] & hc->bmask[pt])) {
+ printk(KERN_INFO
+ "HFC-E1 #%d has overlapping B-channels on fragment #%d\n",
+ E1_cnt + 1, pt);
+ return -EINVAL;
+ }
+ maskcheck |= hc->bmask[pt];
+ printk(KERN_INFO
+ "HFC-E1 #%d uses D-channel on slot %d and a B-channel map of 0x%08x\n",
+ E1_cnt + 1, ch, hc->bmask[pt]);
+ pt++;
+ }
+ hc->ports = pt;
+ }
+ if (hc->ctype == HFC_TYPE_E1 && !dmask[E1_cnt]) {
+ /* default card layout */
+ hc->dnum[0] = 16;
+ hc->bmask[0] = 0xfffefffe;
+ hc->ports = 1;
+ }
/* set chip specific features */
hc->masterclk = -1;
@@ -5091,23 +5157,33 @@ hfcmulti_init(struct hm_map *m, struct pci_dev *pdev,
goto free_card;
}
if (hc->ctype == HFC_TYPE_E1)
- ret_err = init_e1_port(hc, m);
+ ret_err = init_e1_port(hc, m, pt);
else
ret_err = init_multi_port(hc, pt);
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG
- "%s: Registering D-channel, card(%d) port(%d)"
+ "%s: Registering D-channel, card(%d) port(%d) "
"result %d\n",
- __func__, HFC_cnt + 1, pt, ret_err);
+ __func__, HFC_cnt + 1, pt + 1, ret_err);
if (ret_err) {
while (pt) { /* release already registered ports */
pt--;
- release_port(hc, hc->chan[(pt << 2) + 2].dch);
+ if (hc->ctype == HFC_TYPE_E1)
+ release_port(hc,
+ hc->chan[hc->dnum[pt]].dch);
+ else
+ release_port(hc,
+ hc->chan[(pt << 2) + 2].dch);
}
goto free_card;
}
- Port_cnt++;
+ if (hc->ctype != HFC_TYPE_E1)
+ Port_cnt++; /* for each S0 port */
+ }
+ if (hc->ctype == HFC_TYPE_E1) {
+ Port_cnt++; /* for each E1 port */
+ E1_cnt++;
}
/* disp switches */
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index e2c83a2d7691..81363ffa5357 100644
--- a/drivers/isdn/hardware/mISDN/hfcpci.c
+++ b/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -453,7 +453,7 @@ hfcpci_empty_bfifo(struct bchannel *bch, struct bzfifo *bz,
}
bz->za[new_f2].z2 = cpu_to_le16(new_z2);
bz->f2 = new_f2; /* next buffer */
- recv_Bchannel(bch, MISDN_ID_ANY);
+ recv_Bchannel(bch, MISDN_ID_ANY, false);
}
}
@@ -565,11 +565,6 @@ hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *rxbz,
if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
new_z2 -= B_FIFO_SIZE; /* buffer wrap */
- if (fcnt_rx > MAX_DATA_SIZE) { /* flush, if oversized */
- *z2r = cpu_to_le16(new_z2); /* new position */
- return;
- }
-
fcnt_tx = le16_to_cpu(*z2t) - le16_to_cpu(*z1t);
if (fcnt_tx <= 0)
fcnt_tx += B_FIFO_SIZE;
@@ -577,8 +572,16 @@ hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *rxbz,
fcnt_tx = B_FIFO_SIZE - fcnt_tx;
/* remaining bytes to send (bytes in tx-fifo) */
- bch->rx_skb = mI_alloc_skb(fcnt_rx, GFP_ATOMIC);
- if (bch->rx_skb) {
+ if (test_bit(FLG_RX_OFF, &bch->Flags)) {
+ bch->dropcnt += fcnt_rx;
+ *z2r = cpu_to_le16(new_z2);
+ return;
+ }
+ maxlen = bchannel_get_rxbuf(bch, fcnt_rx);
+ if (maxlen < 0) {
+ pr_warning("B%d: No bufferspace for %d bytes\n",
+ bch->nr, fcnt_rx);
+ } else {
ptr = skb_put(bch->rx_skb, fcnt_rx);
if (le16_to_cpu(*z2r) + fcnt_rx <= B_FIFO_SIZE + B_SUB_VAL)
maxlen = fcnt_rx; /* complete transfer */
@@ -596,10 +599,8 @@ hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *rxbz,
ptr1 = bdata; /* start of buffer */
memcpy(ptr, ptr1, fcnt_rx); /* rest */
}
- recv_Bchannel(bch, fcnt_tx); /* bch, id */
- } else
- printk(KERN_WARNING "HFCPCI: receive out of memory\n");
-
+ recv_Bchannel(bch, fcnt_tx, false); /* bch, id, !force */
+ }
*z2r = cpu_to_le16(new_z2); /* new position */
}
@@ -760,9 +761,14 @@ hfcpci_fill_fifo(struct bchannel *bch)
if ((bch->debug & DEBUG_HW_BCHANNEL) && !(bch->debug & DEBUG_HW_BFIFO))
printk(KERN_DEBUG "%s\n", __func__);
- if ((!bch->tx_skb) || bch->tx_skb->len <= 0)
- return;
- count = bch->tx_skb->len - bch->tx_idx;
+ if ((!bch->tx_skb) || bch->tx_skb->len == 0) {
+ if (!test_bit(FLG_FILLEMPTY, &bch->Flags) &&
+ !test_bit(FLG_TRANSPARENT, &bch->Flags))
+ return;
+ count = HFCPCI_FILLEMPTY;
+ } else {
+ count = bch->tx_skb->len - bch->tx_idx;
+ }
if ((bch->nr & 2) && (!hc->hw.bswapped)) {
bz = &((union fifo_area *)(hc->hw.fifos))->b_chans.txbz_b2;
bdata = ((union fifo_area *)(hc->hw.fifos))->b_chans.txdat_b2;
@@ -781,16 +787,10 @@ hfcpci_fill_fifo(struct bchannel *bch)
fcnt = le16_to_cpu(*z2t) - le16_to_cpu(*z1t);
if (fcnt <= 0)
fcnt += B_FIFO_SIZE;
- /* fcnt contains available bytes in fifo */
- fcnt = B_FIFO_SIZE - fcnt;
- /* remaining bytes to send (bytes in fifo) */
-
- /* "fill fifo if empty" feature */
- if (test_bit(FLG_FILLEMPTY, &bch->Flags) && !fcnt) {
- /* printk(KERN_DEBUG "%s: buffer empty, so we have "
- "underrun\n", __func__); */
- /* fill buffer, to prevent future underrun */
- count = HFCPCI_FILLEMPTY;
+ if (test_bit(FLG_FILLEMPTY, &bch->Flags)) {
+ /* fcnt contains available bytes in fifo */
+ if (count > fcnt)
+ count = fcnt;
new_z1 = le16_to_cpu(*z1t) + count;
/* new buffer Position */
if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL))
@@ -802,17 +802,20 @@ hfcpci_fill_fifo(struct bchannel *bch)
printk(KERN_DEBUG "hfcpci_FFt fillempty "
"fcnt(%d) maxl(%d) nz1(%x) dst(%p)\n",
fcnt, maxlen, new_z1, dst);
- fcnt += count;
if (maxlen > count)
maxlen = count; /* limit size */
- memset(dst, 0x2a, maxlen); /* first copy */
+ memset(dst, bch->fill[0], maxlen); /* first copy */
count -= maxlen; /* remaining bytes */
if (count) {
dst = bdata; /* start of buffer */
- memset(dst, 0x2a, count);
+ memset(dst, bch->fill[0], count);
}
*z1t = cpu_to_le16(new_z1); /* now send data */
+ return;
}
+ /* fcnt contains available bytes in fifo */
+ fcnt = B_FIFO_SIZE - fcnt;
+ /* remaining bytes to send (bytes in fifo) */
next_t_frame:
count = bch->tx_skb->len - bch->tx_idx;
@@ -849,9 +852,6 @@ hfcpci_fill_fifo(struct bchannel *bch)
*z1t = cpu_to_le16(new_z1); /* now send data */
if (bch->tx_idx < bch->tx_skb->len)
return;
- /* send confirm, on trans, free on hdlc. */
- if (test_bit(FLG_TRANSPARENT, &bch->Flags))
- confirm_Bsend(bch);
dev_kfree_skb(bch->tx_skb);
if (get_next_bframe(bch))
goto next_t_frame;
@@ -1533,24 +1533,7 @@ deactivate_bchannel(struct bchannel *bch)
static int
channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
{
- int ret = 0;
-
- switch (cq->op) {
- case MISDN_CTRL_GETOP:
- cq->op = MISDN_CTRL_FILL_EMPTY;
- break;
- case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */
- test_and_set_bit(FLG_FILLEMPTY, &bch->Flags);
- if (debug & DEBUG_HW_OPEN)
- printk(KERN_DEBUG "%s: FILL_EMPTY request (nr=%d "
- "off=%d)\n", __func__, bch->nr, !!cq->p1);
- break;
- default:
- printk(KERN_WARNING "%s: unknown Op %x\n", __func__, cq->op);
- ret = -EINVAL;
- break;
- }
- return ret;
+ return mISDN_ctrl_bchannel(bch, cq);
}
static int
hfc_bctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
@@ -1581,8 +1564,7 @@ hfc_bctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
break;
case CLOSE_CHANNEL:
test_and_clear_bit(FLG_OPEN, &bch->Flags);
- if (test_bit(FLG_ACTIVE, &bch->Flags))
- deactivate_bchannel(bch);
+ deactivate_bchannel(bch);
ch->protocol = ISDN_P_NONE;
ch->peer = NULL;
module_put(THIS_MODULE);
@@ -1692,22 +1674,17 @@ hfcpci_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
struct hfc_pci *hc = bch->hw;
int ret = -EINVAL;
struct mISDNhead *hh = mISDN_HEAD_P(skb);
- unsigned int id;
- u_long flags;
+ unsigned long flags;
switch (hh->prim) {
case PH_DATA_REQ:
spin_lock_irqsave(&hc->lock, flags);
ret = bchannel_senddata(bch, skb);
if (ret > 0) { /* direct TX */
- id = hh->id; /* skb can be freed */
hfcpci_fill_fifo(bch);
ret = 0;
- spin_unlock_irqrestore(&hc->lock, flags);
- if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
- queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
- } else
- spin_unlock_irqrestore(&hc->lock, flags);
+ }
+ spin_unlock_irqrestore(&hc->lock, flags);
return ret;
case PH_ACTIVATE_REQ:
spin_lock_irqsave(&hc->lock, flags);
@@ -1819,7 +1796,7 @@ channel_ctrl(struct hfc_pci *hc, struct mISDN_ctrl_req *cq)
switch (cq->op) {
case MISDN_CTRL_GETOP:
cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_CONNECT |
- MISDN_CTRL_DISCONNECT;
+ MISDN_CTRL_DISCONNECT | MISDN_CTRL_L1_TIMER3;
break;
case MISDN_CTRL_LOOP:
/* channel 0 disabled loop */
@@ -1896,6 +1873,9 @@ channel_ctrl(struct hfc_pci *hc, struct mISDN_ctrl_req *cq)
Write_hfc(hc, HFCPCI_CONNECT, hc->hw.conn);
hc->hw.trm &= 0x7f; /* disable IOM-loop */
break;
+ case MISDN_CTRL_L1_TIMER3:
+ ret = l1_event(hc->dch.l1, HW_TIMER3_VALUE | (cq->p1 & 0xff));
+ break;
default:
printk(KERN_WARNING "%s: unknown Op %x\n",
__func__, cq->op);
@@ -1969,7 +1949,6 @@ open_bchannel(struct hfc_pci *hc, struct channel_req *rq)
bch = &hc->bch[rq->adr.channel - 1];
if (test_and_set_bit(FLG_OPEN, &bch->Flags))
return -EBUSY; /* b-channel can be only open once */
- test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
bch->ch.protocol = rq->protocol;
rq->ch = &bch->ch; /* TODO: E-channel */
if (!try_module_get(THIS_MODULE))
@@ -2121,7 +2100,7 @@ setup_card(struct hfc_pci *card)
card->bch[i].nr = i + 1;
set_channelmap(i + 1, card->dch.dev.channelmap);
card->bch[i].debug = debug;
- mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM);
+ mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM, poll >> 1);
card->bch[i].hw = card;
card->bch[i].ch.send = hfcpci_l2l1B;
card->bch[i].ch.ctrl = hfc_bctrl;
diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c
index cddb769a8b12..c65c3440cd70 100644
--- a/drivers/isdn/hardware/mISDN/hfcsusb.c
+++ b/drivers/isdn/hardware/mISDN/hfcsusb.c
@@ -226,19 +226,12 @@ hfcusb_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
if (debug & DBG_HFC_CALL_TRACE)
printk(KERN_DEBUG "%s: %s PH_DATA_REQ ret(%i)\n",
hw->name, __func__, ret);
- if (ret > 0) {
- /*
- * other l1 drivers don't send early confirms on
- * transp data, but hfcsusb does because tx_next
- * skb is needed in tx_iso_complete()
- */
- queue_ch_frame(ch, PH_DATA_CNF, hh->id, NULL);
+ if (ret > 0)
ret = 0;
- }
return ret;
case PH_ACTIVATE_REQ:
if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags)) {
- hfcsusb_start_endpoint(hw, bch->nr);
+ hfcsusb_start_endpoint(hw, bch->nr - 1);
ret = hfcsusb_setup_bch(bch, ch->protocol);
} else
ret = 0;
@@ -498,16 +491,9 @@ open_bchannel(struct hfcsusb *hw, struct channel_req *rq)
bch = &hw->bch[rq->adr.channel - 1];
if (test_and_set_bit(FLG_OPEN, &bch->Flags))
return -EBUSY; /* b-channel can be only open once */
- test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
bch->ch.protocol = rq->protocol;
rq->ch = &bch->ch;
- /* start USB endpoint for bchannel */
- if (rq->adr.channel == 1)
- hfcsusb_start_endpoint(hw, HFC_CHAN_B1);
- else
- hfcsusb_start_endpoint(hw, HFC_CHAN_B2);
-
if (!try_module_get(THIS_MODULE))
printk(KERN_WARNING "%s: %s:cannot get module\n",
hw->name, __func__);
@@ -819,24 +805,7 @@ hfcsusb_ph_command(struct hfcsusb *hw, u_char command)
static int
channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
{
- int ret = 0;
-
- switch (cq->op) {
- case MISDN_CTRL_GETOP:
- cq->op = MISDN_CTRL_FILL_EMPTY;
- break;
- case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */
- test_and_set_bit(FLG_FILLEMPTY, &bch->Flags);
- if (debug & DEBUG_HW_OPEN)
- printk(KERN_DEBUG "%s: FILL_EMPTY request (nr=%d "
- "off=%d)\n", __func__, bch->nr, !!cq->p1);
- break;
- default:
- printk(KERN_WARNING "%s: unknown Op %x\n", __func__, cq->op);
- ret = -EINVAL;
- break;
- }
- return ret;
+ return mISDN_ctrl_bchannel(bch, cq);
}
/* collect data from incoming interrupt or isochron USB data */
@@ -873,7 +842,21 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
hdlc = 1;
}
if (fifo->bch) {
+ if (test_bit(FLG_RX_OFF, &fifo->bch->Flags)) {
+ fifo->bch->dropcnt += len;
+ spin_unlock(&hw->lock);
+ return;
+ }
+ maxlen = bchannel_get_rxbuf(fifo->bch, len);
rx_skb = fifo->bch->rx_skb;
+ if (maxlen < 0) {
+ if (rx_skb)
+ skb_trim(rx_skb, 0);
+ pr_warning("%s.B%d: No bufferspace for %d bytes\n",
+ hw->name, fifo->bch->nr, len);
+ spin_unlock(&hw->lock);
+ return;
+ }
maxlen = fifo->bch->maxlen;
hdlc = test_bit(FLG_HDLC, &fifo->bch->Flags);
}
@@ -883,25 +866,22 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
hdlc = 1;
}
- if (!rx_skb) {
- rx_skb = mI_alloc_skb(maxlen, GFP_ATOMIC);
- if (rx_skb) {
- if (fifo->dch)
- fifo->dch->rx_skb = rx_skb;
- if (fifo->bch)
- fifo->bch->rx_skb = rx_skb;
- if (fifo->ech)
- fifo->ech->rx_skb = rx_skb;
- skb_trim(rx_skb, 0);
- } else {
- printk(KERN_DEBUG "%s: %s: No mem for rx_skb\n",
- hw->name, __func__);
- spin_unlock(&hw->lock);
- return;
- }
- }
-
if (fifo->dch || fifo->ech) {
+ if (!rx_skb) {
+ rx_skb = mI_alloc_skb(maxlen, GFP_ATOMIC);
+ if (rx_skb) {
+ if (fifo->dch)
+ fifo->dch->rx_skb = rx_skb;
+ if (fifo->ech)
+ fifo->ech->rx_skb = rx_skb;
+ skb_trim(rx_skb, 0);
+ } else {
+ printk(KERN_DEBUG "%s: %s: No mem for rx_skb\n",
+ hw->name, __func__);
+ spin_unlock(&hw->lock);
+ return;
+ }
+ }
/* D/E-Channel SKB range check */
if ((rx_skb->len + len) >= MAX_DFRAME_LEN_L1) {
printk(KERN_DEBUG "%s: %s: sbk mem exceeded "
@@ -911,16 +891,6 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
spin_unlock(&hw->lock);
return;
}
- } else if (fifo->bch) {
- /* B-Channel SKB range check */
- if ((rx_skb->len + len) >= (MAX_BCH_SIZE + 3)) {
- printk(KERN_DEBUG "%s: %s: sbk mem exceeded "
- "for fifo(%d) HFCUSB_B_RX\n",
- hw->name, __func__, fifon);
- skb_trim(rx_skb, 0);
- spin_unlock(&hw->lock);
- return;
- }
}
memcpy(skb_put(rx_skb, len), data, len);
@@ -948,7 +918,8 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
if (fifo->dch)
recv_Dchannel(fifo->dch);
if (fifo->bch)
- recv_Bchannel(fifo->bch, MISDN_ID_ANY);
+ recv_Bchannel(fifo->bch, MISDN_ID_ANY,
+ 0);
if (fifo->ech)
recv_Echannel(fifo->ech,
&hw->dch);
@@ -969,8 +940,7 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
}
} else {
/* deliver transparent data to layer2 */
- if (rx_skb->len >= poll)
- recv_Bchannel(fifo->bch, MISDN_ID_ANY);
+ recv_Bchannel(fifo->bch, MISDN_ID_ANY, false);
}
spin_unlock(&hw->lock);
}
@@ -1200,8 +1170,8 @@ tx_iso_complete(struct urb *urb)
int k, tx_offset, num_isoc_packets, sink, remain, current_len,
errcode, hdlc, i;
int *tx_idx;
- int frame_complete, fifon, status;
- __u8 threshbit;
+ int frame_complete, fifon, status, fillempty = 0;
+ __u8 threshbit, *p;
spin_lock(&hw->lock);
if (fifo->stop_gracefull) {
@@ -1219,6 +1189,9 @@ tx_iso_complete(struct urb *urb)
tx_skb = fifo->bch->tx_skb;
tx_idx = &fifo->bch->tx_idx;
hdlc = test_bit(FLG_HDLC, &fifo->bch->Flags);
+ if (!tx_skb && !hdlc &&
+ test_bit(FLG_FILLEMPTY, &fifo->bch->Flags))
+ fillempty = 1;
} else {
printk(KERN_DEBUG "%s: %s: neither BCH nor DCH\n",
hw->name, __func__);
@@ -1277,6 +1250,8 @@ tx_iso_complete(struct urb *urb)
/* Generate next ISO Packets */
if (tx_skb)
remain = tx_skb->len - *tx_idx;
+ else if (fillempty)
+ remain = 15; /* > not complete */
else
remain = 0;
@@ -1307,15 +1282,20 @@ tx_iso_complete(struct urb *urb)
}
/* copy tx data to iso-urb buffer */
- memcpy(context_iso_urb->buffer + tx_offset + 1,
- (tx_skb->data + *tx_idx), current_len);
- *tx_idx += current_len;
-
+ p = context_iso_urb->buffer + tx_offset + 1;
+ if (fillempty) {
+ memset(p, fifo->bch->fill[0],
+ current_len);
+ } else {
+ memcpy(p, (tx_skb->data + *tx_idx),
+ current_len);
+ *tx_idx += current_len;
+ }
urb->iso_frame_desc[k].offset = tx_offset;
urb->iso_frame_desc[k].length = current_len + 1;
/* USB data log for every D ISO out */
- if ((fifon == HFCUSB_D_RX) &&
+ if ((fifon == HFCUSB_D_RX) && !fillempty &&
(debug & DBG_HFC_USB_VERBOSE)) {
printk(KERN_DEBUG
"%s: %s (%d/%d) offs(%d) len(%d) ",
@@ -1365,12 +1345,8 @@ tx_iso_complete(struct urb *urb)
if (fifo->dch && get_next_dframe(fifo->dch))
tx_skb = fifo->dch->tx_skb;
else if (fifo->bch &&
- get_next_bframe(fifo->bch)) {
- if (test_bit(FLG_TRANSPARENT,
- &fifo->bch->Flags))
- confirm_Bsend(fifo->bch);
+ get_next_bframe(fifo->bch))
tx_skb = fifo->bch->tx_skb;
- }
}
}
errcode = usb_submit_urb(urb, GFP_ATOMIC);
@@ -1812,7 +1788,7 @@ deactivate_bchannel(struct bchannel *bch)
mISDN_clear_bchannel(bch);
spin_unlock_irqrestore(&hw->lock, flags);
hfcsusb_setup_bch(bch, ISDN_P_NONE);
- hfcsusb_stop_endpoint(hw, bch->nr);
+ hfcsusb_stop_endpoint(hw, bch->nr - 1);
}
/*
@@ -1836,8 +1812,7 @@ hfc_bctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
case CLOSE_CHANNEL:
test_and_clear_bit(FLG_OPEN, &bch->Flags);
- if (test_bit(FLG_ACTIVE, &bch->Flags))
- deactivate_bchannel(bch);
+ deactivate_bchannel(bch);
ch->protocol = ISDN_P_NONE;
ch->peer = NULL;
module_put(THIS_MODULE);
@@ -1883,7 +1858,7 @@ setup_instance(struct hfcsusb *hw, struct device *parent)
hw->bch[i].nr = i + 1;
set_channelmap(i + 1, hw->dch.dev.channelmap);
hw->bch[i].debug = debug;
- mISDN_initbchannel(&hw->bch[i], MAX_DATA_MEM);
+ mISDN_initbchannel(&hw->bch[i], MAX_DATA_MEM, poll >> 1);
hw->bch[i].hw = hw;
hw->bch[i].ch.send = hfcusb_l2l1B;
hw->bch[i].ch.ctrl = hfc_bctrl;
diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c
index 884369f09cad..752e0825591f 100644
--- a/drivers/isdn/hardware/mISDN/mISDNipac.c
+++ b/drivers/isdn/hardware/mISDN/mISDNipac.c
@@ -603,10 +603,11 @@ isac_l1hw(struct mISDNchannel *ch, struct sk_buff *skb)
}
static int
-isac_ctrl(struct isac_hw *isac, u32 cmd, u_long para)
+isac_ctrl(struct isac_hw *isac, u32 cmd, unsigned long para)
{
u8 tl = 0;
- u_long flags;
+ unsigned long flags;
+ int ret = 0;
switch (cmd) {
case HW_TESTLOOP:
@@ -626,12 +627,15 @@ isac_ctrl(struct isac_hw *isac, u32 cmd, u_long para)
}
spin_unlock_irqrestore(isac->hwlock, flags);
break;
+ case HW_TIMER3_VALUE:
+ ret = l1_event(isac->dch.l1, HW_TIMER3_VALUE | (para & 0xff));
+ break;
default:
pr_debug("%s: %s unknown command %x %lx\n", isac->name,
__func__, cmd, para);
- return -1;
+ ret = -1;
}
- return 0;
+ return ret;
}
static int
@@ -929,22 +933,21 @@ static void
hscx_empty_fifo(struct hscx_hw *hscx, u8 count)
{
u8 *p;
+ int maxlen;
pr_debug("%s: B%1d %d\n", hscx->ip->name, hscx->bch.nr, count);
- if (!hscx->bch.rx_skb) {
- hscx->bch.rx_skb = mI_alloc_skb(hscx->bch.maxlen, GFP_ATOMIC);
- if (!hscx->bch.rx_skb) {
- pr_info("%s: B receive out of memory\n",
- hscx->ip->name);
- hscx_cmdr(hscx, 0x80); /* RMC */
- return;
- }
+ if (test_bit(FLG_RX_OFF, &hscx->bch.Flags)) {
+ hscx->bch.dropcnt += count;
+ hscx_cmdr(hscx, 0x80); /* RMC */
+ return;
}
- if ((hscx->bch.rx_skb->len + count) > hscx->bch.maxlen) {
- pr_debug("%s: overrun %d\n", hscx->ip->name,
- hscx->bch.rx_skb->len + count);
- skb_trim(hscx->bch.rx_skb, 0);
+ maxlen = bchannel_get_rxbuf(&hscx->bch, count);
+ if (maxlen < 0) {
hscx_cmdr(hscx, 0x80); /* RMC */
+ if (hscx->bch.rx_skb)
+ skb_trim(hscx->bch.rx_skb, 0);
+ pr_warning("%s.B%d: No bufferspace for %d bytes\n",
+ hscx->ip->name, hscx->bch.nr, count);
return;
}
p = skb_put(hscx->bch.rx_skb, count);
@@ -971,22 +974,28 @@ hscx_fill_fifo(struct hscx_hw *hscx)
int count, more;
u8 *p;
- if (!hscx->bch.tx_skb)
- return;
- count = hscx->bch.tx_skb->len - hscx->bch.tx_idx;
- if (count <= 0)
- return;
- p = hscx->bch.tx_skb->data + hscx->bch.tx_idx;
-
- more = test_bit(FLG_TRANSPARENT, &hscx->bch.Flags) ? 1 : 0;
- if (count > hscx->fifo_size) {
+ if (!hscx->bch.tx_skb) {
+ if (!test_bit(FLG_TX_EMPTY, &hscx->bch.Flags))
+ return;
count = hscx->fifo_size;
more = 1;
- }
- pr_debug("%s: B%1d %d/%d/%d\n", hscx->ip->name, hscx->bch.nr, count,
- hscx->bch.tx_idx, hscx->bch.tx_skb->len);
- hscx->bch.tx_idx += count;
+ p = hscx->log;
+ memset(p, hscx->bch.fill[0], count);
+ } else {
+ count = hscx->bch.tx_skb->len - hscx->bch.tx_idx;
+ if (count <= 0)
+ return;
+ p = hscx->bch.tx_skb->data + hscx->bch.tx_idx;
+ more = test_bit(FLG_TRANSPARENT, &hscx->bch.Flags) ? 1 : 0;
+ if (count > hscx->fifo_size) {
+ count = hscx->fifo_size;
+ more = 1;
+ }
+ pr_debug("%s: B%1d %d/%d/%d\n", hscx->ip->name, hscx->bch.nr,
+ count, hscx->bch.tx_idx, hscx->bch.tx_skb->len);
+ hscx->bch.tx_idx += count;
+ }
if (hscx->ip->type & IPAC_TYPE_IPACX)
hscx->ip->write_fifo(hscx->ip->hw,
hscx->off + IPACX_XFIFOB, p, count);
@@ -997,7 +1006,7 @@ hscx_fill_fifo(struct hscx_hw *hscx)
}
hscx_cmdr(hscx, more ? 0x08 : 0x0a);
- if (hscx->bch.debug & DEBUG_HW_BFIFO) {
+ if (hscx->bch.tx_skb && (hscx->bch.debug & DEBUG_HW_BFIFO)) {
snprintf(hscx->log, 64, "B%1d-send %s %d ",
hscx->bch.nr, hscx->ip->name, count);
print_hex_dump_bytes(hscx->log, DUMP_PREFIX_OFFSET, p, count);
@@ -1007,17 +1016,17 @@ hscx_fill_fifo(struct hscx_hw *hscx)
static void
hscx_xpr(struct hscx_hw *hx)
{
- if (hx->bch.tx_skb && hx->bch.tx_idx < hx->bch.tx_skb->len)
+ if (hx->bch.tx_skb && hx->bch.tx_idx < hx->bch.tx_skb->len) {
hscx_fill_fifo(hx);
- else {
- if (hx->bch.tx_skb) {
- /* send confirm, on trans, free on hdlc. */
- if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags))
- confirm_Bsend(&hx->bch);
+ } else {
+ if (hx->bch.tx_skb)
dev_kfree_skb(hx->bch.tx_skb);
- }
- if (get_next_bframe(&hx->bch))
+ if (get_next_bframe(&hx->bch)) {
+ hscx_fill_fifo(hx);
+ test_and_clear_bit(FLG_TX_EMPTY, &hx->bch.Flags);
+ } else if (test_bit(FLG_TX_EMPTY, &hx->bch.Flags)) {
hscx_fill_fifo(hx);
+ }
}
}
@@ -1069,7 +1078,7 @@ ipac_rme(struct hscx_hw *hx)
skb_trim(hx->bch.rx_skb, 0);
} else {
skb_trim(hx->bch.rx_skb, hx->bch.rx_skb->len - 1);
- recv_Bchannel(&hx->bch, 0);
+ recv_Bchannel(&hx->bch, 0, false);
}
}
@@ -1120,11 +1129,8 @@ ipac_irq(struct hscx_hw *hx, u8 ista)
if (istab & IPACX_B_RPF) {
hscx_empty_fifo(hx, hx->fifo_size);
- if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags)) {
- /* receive transparent audio data */
- if (hx->bch.rx_skb)
- recv_Bchannel(&hx->bch, 0);
- }
+ if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags))
+ recv_Bchannel(&hx->bch, 0, false);
}
if (istab & IPACX_B_RFO) {
@@ -1137,7 +1143,9 @@ ipac_irq(struct hscx_hw *hx, u8 ista)
if (istab & IPACX_B_XDU) {
if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags)) {
- hscx_fill_fifo(hx);
+ if (test_bit(FLG_FILLEMPTY, &hx->bch.Flags))
+ test_and_set_bit(FLG_TX_EMPTY, &hx->bch.Flags);
+ hscx_xpr(hx);
return;
}
pr_debug("%s: B%1d XDU error at len %d\n", hx->ip->name,
@@ -1338,22 +1346,17 @@ hscx_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
struct hscx_hw *hx = container_of(bch, struct hscx_hw, bch);
int ret = -EINVAL;
struct mISDNhead *hh = mISDN_HEAD_P(skb);
- u32 id;
- u_long flags;
+ unsigned long flags;
switch (hh->prim) {
case PH_DATA_REQ:
spin_lock_irqsave(hx->ip->hwlock, flags);
ret = bchannel_senddata(bch, skb);
if (ret > 0) { /* direct TX */
- id = hh->id; /* skb can be freed */
ret = 0;
hscx_fill_fifo(hx);
- spin_unlock_irqrestore(hx->ip->hwlock, flags);
- if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
- queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
- } else
- spin_unlock_irqrestore(hx->ip->hwlock, flags);
+ }
+ spin_unlock_irqrestore(hx->ip->hwlock, flags);
return ret;
case PH_ACTIVATE_REQ:
spin_lock_irqsave(hx->ip->hwlock, flags);
@@ -1388,20 +1391,7 @@ hscx_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
static int
channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
{
- int ret = 0;
-
- switch (cq->op) {
- case MISDN_CTRL_GETOP:
- cq->op = 0;
- break;
- /* Nothing implemented yet */
- case MISDN_CTRL_FILL_EMPTY:
- default:
- pr_info("%s: unknown Op %x\n", __func__, cq->op);
- ret = -EINVAL;
- break;
- }
- return ret;
+ return mISDN_ctrl_bchannel(bch, cq);
}
static int
@@ -1416,15 +1406,10 @@ hscx_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
switch (cmd) {
case CLOSE_CHANNEL:
test_and_clear_bit(FLG_OPEN, &bch->Flags);
- if (test_bit(FLG_ACTIVE, &bch->Flags)) {
- spin_lock_irqsave(hx->ip->hwlock, flags);
- mISDN_freebchannel(bch);
- hscx_mode(hx, ISDN_P_NONE);
- spin_unlock_irqrestore(hx->ip->hwlock, flags);
- } else {
- skb_queue_purge(&bch->rqueue);
- bch->rcount = 0;
- }
+ spin_lock_irqsave(hx->ip->hwlock, flags);
+ mISDN_freebchannel(bch);
+ hscx_mode(hx, ISDN_P_NONE);
+ spin_unlock_irqrestore(hx->ip->hwlock, flags);
ch->protocol = ISDN_P_NONE;
ch->peer = NULL;
module_put(hx->ip->owner);
@@ -1526,7 +1511,7 @@ channel_ctrl(struct ipac_hw *ipac, struct mISDN_ctrl_req *cq)
switch (cq->op) {
case MISDN_CTRL_GETOP:
- cq->op = MISDN_CTRL_LOOP;
+ cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_L1_TIMER3;
break;
case MISDN_CTRL_LOOP:
/* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
@@ -1536,6 +1521,9 @@ channel_ctrl(struct ipac_hw *ipac, struct mISDN_ctrl_req *cq)
}
ret = ipac->ctrl(ipac, HW_TESTLOOP, cq->channel);
break;
+ case MISDN_CTRL_L1_TIMER3:
+ ret = ipac->isac.ctrl(&ipac->isac, HW_TIMER3_VALUE, cq->p1);
+ break;
default:
pr_info("%s: unknown CTRL OP %x\n", ipac->name, cq->op);
ret = -EINVAL;
@@ -1621,7 +1609,8 @@ mISDNipac_init(struct ipac_hw *ipac, void *hw)
set_channelmap(i + 1, ipac->isac.dch.dev.channelmap);
list_add(&ipac->hscx[i].bch.ch.list,
&ipac->isac.dch.dev.bchannels);
- mISDN_initbchannel(&ipac->hscx[i].bch, MAX_DATA_MEM);
+ mISDN_initbchannel(&ipac->hscx[i].bch, MAX_DATA_MEM,
+ ipac->hscx[i].fifo_size);
ipac->hscx[i].bch.ch.nr = i + 1;
ipac->hscx[i].bch.ch.send = &hscx_l2l1;
ipac->hscx[i].bch.ch.ctrl = hscx_bctrl;
diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c
index 9a6da6edcfa8..be5973ded6d6 100644
--- a/drivers/isdn/hardware/mISDN/mISDNisar.c
+++ b/drivers/isdn/hardware/mISDN/mISDNisar.c
@@ -421,13 +421,19 @@ deliver_status(struct isar_ch *ch, int status)
static inline void
isar_rcv_frame(struct isar_ch *ch)
{
- u8 *ptr;
+ u8 *ptr;
+ int maxlen;
if (!ch->is->clsb) {
pr_debug("%s; ISAR zero len frame\n", ch->is->name);
ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
return;
}
+ if (test_bit(FLG_RX_OFF, &ch->bch.Flags)) {
+ ch->bch.dropcnt += ch->is->clsb;
+ ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
+ return;
+ }
switch (ch->bch.state) {
case ISDN_P_NONE:
pr_debug("%s: ISAR protocol 0 spurious IIS_RDATA %x/%x/%x\n",
@@ -437,36 +443,22 @@ isar_rcv_frame(struct isar_ch *ch)
case ISDN_P_B_RAW:
case ISDN_P_B_L2DTMF:
case ISDN_P_B_MODEM_ASYNC:
- if (!ch->bch.rx_skb) {
- ch->bch.rx_skb = mI_alloc_skb(ch->bch.maxlen,
- GFP_ATOMIC);
- if (unlikely(!ch->bch.rx_skb)) {
- pr_info("%s: B receive out of memory\n",
- ch->is->name);
- ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
- break;
- }
+ maxlen = bchannel_get_rxbuf(&ch->bch, ch->is->clsb);
+ if (maxlen < 0) {
+ pr_warning("%s.B%d: No bufferspace for %d bytes\n",
+ ch->is->name, ch->bch.nr, ch->is->clsb);
+ ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
+ break;
}
rcv_mbox(ch->is, skb_put(ch->bch.rx_skb, ch->is->clsb));
- recv_Bchannel(&ch->bch, 0);
+ recv_Bchannel(&ch->bch, 0, false);
break;
case ISDN_P_B_HDLC:
- if (!ch->bch.rx_skb) {
- ch->bch.rx_skb = mI_alloc_skb(ch->bch.maxlen,
- GFP_ATOMIC);
- if (unlikely(!ch->bch.rx_skb)) {
- pr_info("%s: B receive out of memory\n",
- ch->is->name);
- ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
- break;
- }
- }
- if ((ch->bch.rx_skb->len + ch->is->clsb) >
- (ch->bch.maxlen + 2)) {
- pr_debug("%s: incoming packet too large\n",
- ch->is->name);
+ maxlen = bchannel_get_rxbuf(&ch->bch, ch->is->clsb);
+ if (maxlen < 0) {
+ pr_warning("%s.B%d: No bufferspace for %d bytes\n",
+ ch->is->name, ch->bch.nr, ch->is->clsb);
ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
- skb_trim(ch->bch.rx_skb, 0);
break;
}
if (ch->is->cmsb & HDLC_ERROR) {
@@ -494,7 +486,7 @@ isar_rcv_frame(struct isar_ch *ch)
break;
}
skb_trim(ch->bch.rx_skb, ch->bch.rx_skb->len - 2);
- recv_Bchannel(&ch->bch, 0);
+ recv_Bchannel(&ch->bch, 0, false);
}
break;
case ISDN_P_B_T30_FAX:
@@ -530,7 +522,7 @@ isar_rcv_frame(struct isar_ch *ch)
ch->state = STFAX_ESCAPE;
/* set_skb_flag(skb, DF_NOMOREDATA); */
}
- recv_Bchannel(&ch->bch, 0);
+ recv_Bchannel(&ch->bch, 0, false);
if (ch->is->cmsb & SART_NMD)
deliver_status(ch, HW_MOD_NOCARR);
break;
@@ -570,7 +562,7 @@ isar_rcv_frame(struct isar_ch *ch)
break;
}
skb_trim(ch->bch.rx_skb, ch->bch.rx_skb->len - 2);
- recv_Bchannel(&ch->bch, 0);
+ recv_Bchannel(&ch->bch, 0, false);
}
if (ch->is->cmsb & SART_NMD) { /* ABORT */
pr_debug("%s: isar_rcv_frame: no more data\n",
@@ -598,16 +590,25 @@ isar_fill_fifo(struct isar_ch *ch)
u8 msb;
u8 *ptr;
- pr_debug("%s: ch%d tx_skb %p tx_idx %d\n",
- ch->is->name, ch->bch.nr, ch->bch.tx_skb, ch->bch.tx_idx);
- if (!ch->bch.tx_skb)
+ pr_debug("%s: ch%d tx_skb %d tx_idx %d\n", ch->is->name, ch->bch.nr,
+ ch->bch.tx_skb ? ch->bch.tx_skb->len : -1, ch->bch.tx_idx);
+ if (!(ch->is->bstat &
+ (ch->dpath == 1 ? BSTAT_RDM1 : BSTAT_RDM2)))
+ return;
+ if (!ch->bch.tx_skb) {
+ if (!test_bit(FLG_TX_EMPTY, &ch->bch.Flags) ||
+ (ch->bch.state != ISDN_P_B_RAW))
+ return;
+ count = ch->mml;
+ /* use the card buffer */
+ memset(ch->is->buf, ch->bch.fill[0], count);
+ send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA,
+ 0, count, ch->is->buf);
return;
+ }
count = ch->bch.tx_skb->len - ch->bch.tx_idx;
if (count <= 0)
return;
- if (!(ch->is->bstat &
- (ch->dpath == 1 ? BSTAT_RDM1 : BSTAT_RDM2)))
- return;
if (count > ch->mml) {
msb = 0;
count = ch->mml;
@@ -686,9 +687,9 @@ sel_bch_isar(struct isar_hw *isar, u8 dpath)
static void
send_next(struct isar_ch *ch)
{
- pr_debug("%s: %s ch%d tx_skb %p tx_idx %d\n",
- ch->is->name, __func__, ch->bch.nr,
- ch->bch.tx_skb, ch->bch.tx_idx);
+ pr_debug("%s: %s ch%d tx_skb %d tx_idx %d\n", ch->is->name, __func__,
+ ch->bch.nr, ch->bch.tx_skb ? ch->bch.tx_skb->len : -1,
+ ch->bch.tx_idx);
if (ch->bch.state == ISDN_P_B_T30_FAX) {
if (ch->cmd == PCTRL_CMD_FTH) {
if (test_bit(FLG_LASTDATA, &ch->bch.Flags)) {
@@ -702,15 +703,14 @@ send_next(struct isar_ch *ch)
}
}
}
- if (ch->bch.tx_skb) {
- /* send confirm, on trans, free on hdlc. */
- if (test_bit(FLG_TRANSPARENT, &ch->bch.Flags))
- confirm_Bsend(&ch->bch);
+ if (ch->bch.tx_skb)
dev_kfree_skb(ch->bch.tx_skb);
- }
- if (get_next_bframe(&ch->bch))
+ if (get_next_bframe(&ch->bch)) {
isar_fill_fifo(ch);
- else {
+ test_and_clear_bit(FLG_TX_EMPTY, &ch->bch.Flags);
+ } else if (test_bit(FLG_TX_EMPTY, &ch->bch.Flags)) {
+ isar_fill_fifo(ch);
+ } else {
if (test_and_clear_bit(FLG_DLEETX, &ch->bch.Flags)) {
if (test_and_clear_bit(FLG_LASTDATA,
&ch->bch.Flags)) {
@@ -724,6 +724,8 @@ send_next(struct isar_ch *ch)
} else {
deliver_status(ch, HW_MOD_CONNECT);
}
+ } else if (test_bit(FLG_FILLEMPTY, &ch->bch.Flags)) {
+ test_and_set_bit(FLG_TX_EMPTY, &ch->bch.Flags);
}
}
}
@@ -1487,14 +1489,10 @@ isar_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
spin_lock_irqsave(ich->is->hwlock, flags);
ret = bchannel_senddata(bch, skb);
if (ret > 0) { /* direct TX */
- id = hh->id; /* skb can be freed */
ret = 0;
isar_fill_fifo(ich);
- spin_unlock_irqrestore(ich->is->hwlock, flags);
- if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
- queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
- } else
- spin_unlock_irqrestore(ich->is->hwlock, flags);
+ }
+ spin_unlock_irqrestore(ich->is->hwlock, flags);
return ret;
case PH_ACTIVATE_REQ:
spin_lock_irqsave(ich->is->hwlock, flags);
@@ -1575,20 +1573,7 @@ isar_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
static int
channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
{
- int ret = 0;
-
- switch (cq->op) {
- case MISDN_CTRL_GETOP:
- cq->op = 0;
- break;
- /* Nothing implemented yet */
- case MISDN_CTRL_FILL_EMPTY:
- default:
- pr_info("%s: unknown Op %x\n", __func__, cq->op);
- ret = -EINVAL;
- break;
- }
- return ret;
+ return mISDN_ctrl_bchannel(bch, cq);
}
static int
@@ -1603,15 +1588,10 @@ isar_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
switch (cmd) {
case CLOSE_CHANNEL:
test_and_clear_bit(FLG_OPEN, &bch->Flags);
- if (test_bit(FLG_ACTIVE, &bch->Flags)) {
- spin_lock_irqsave(ich->is->hwlock, flags);
- mISDN_freebchannel(bch);
- modeisar(ich, ISDN_P_NONE);
- spin_unlock_irqrestore(ich->is->hwlock, flags);
- } else {
- skb_queue_purge(&bch->rqueue);
- bch->rcount = 0;
- }
+ spin_lock_irqsave(ich->is->hwlock, flags);
+ mISDN_freebchannel(bch);
+ modeisar(ich, ISDN_P_NONE);
+ spin_unlock_irqrestore(ich->is->hwlock, flags);
ch->protocol = ISDN_P_NONE;
ch->peer = NULL;
module_put(ich->is->owner);
@@ -1677,7 +1657,6 @@ isar_open(struct isar_hw *isar, struct channel_req *rq)
bch = &isar->ch[rq->adr.channel - 1].bch;
if (test_and_set_bit(FLG_OPEN, &bch->Flags))
return -EBUSY; /* b-channel can be only open once */
- test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
bch->ch.protocol = rq->protocol;
rq->ch = &bch->ch;
return 0;
@@ -1691,7 +1670,7 @@ mISDNisar_init(struct isar_hw *isar, void *hw)
isar->hw = hw;
for (i = 0; i < 2; i++) {
isar->ch[i].bch.nr = i + 1;
- mISDN_initbchannel(&isar->ch[i].bch, MAX_DATA_MEM);
+ mISDN_initbchannel(&isar->ch[i].bch, MAX_DATA_MEM, 32);
isar->ch[i].bch.ch.nr = i + 1;
isar->ch[i].bch.ch.send = &isar_l2l1;
isar->ch[i].bch.ch.ctrl = isar_bctrl;
diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c
index c726e09d0981..c3e3e7686273 100644
--- a/drivers/isdn/hardware/mISDN/netjet.c
+++ b/drivers/isdn/hardware/mISDN/netjet.c
@@ -386,24 +386,20 @@ read_dma(struct tiger_ch *bc, u32 idx, int cnt)
bc->bch.nr, idx);
}
bc->lastrx = idx;
- if (!bc->bch.rx_skb) {
- bc->bch.rx_skb = mI_alloc_skb(bc->bch.maxlen, GFP_ATOMIC);
- if (!bc->bch.rx_skb) {
- pr_info("%s: B%1d receive out of memory\n",
- card->name, bc->bch.nr);
- return;
- }
+ if (test_bit(FLG_RX_OFF, &bc->bch.Flags)) {
+ bc->bch.dropcnt += cnt;
+ return;
}
-
- if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags)) {
- if ((bc->bch.rx_skb->len + cnt) > bc->bch.maxlen) {
- pr_debug("%s: B%1d overrun %d\n", card->name,
- bc->bch.nr, bc->bch.rx_skb->len + cnt);
- skb_trim(bc->bch.rx_skb, 0);
- return;
- }
+ stat = bchannel_get_rxbuf(&bc->bch, cnt);
+ /* only transparent use the count here, HDLC overun is detected later */
+ if (stat == ENOMEM) {
+ pr_warning("%s.B%d: No memory for %d bytes\n",
+ card->name, bc->bch.nr, cnt);
+ return;
+ }
+ if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags))
p = skb_put(bc->bch.rx_skb, cnt);
- } else
+ else
p = bc->hrbuf;
for (i = 0; i < cnt; i++) {
@@ -414,48 +410,45 @@ read_dma(struct tiger_ch *bc, u32 idx, int cnt)
idx = 0;
p[i] = val & 0xff;
}
+
+ if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags)) {
+ recv_Bchannel(&bc->bch, 0, false);
+ return;
+ }
+
pn = bc->hrbuf;
-next_frame:
- if (test_bit(FLG_HDLC, &bc->bch.Flags)) {
+ while (cnt > 0) {
stat = isdnhdlc_decode(&bc->hrecv, pn, cnt, &i,
bc->bch.rx_skb->data, bc->bch.maxlen);
- if (stat > 0) /* valid frame received */
+ if (stat > 0) { /* valid frame received */
p = skb_put(bc->bch.rx_skb, stat);
- else if (stat == -HDLC_CRC_ERROR)
+ if (debug & DEBUG_HW_BFIFO) {
+ snprintf(card->log, LOG_SIZE,
+ "B%1d-recv %s %d ", bc->bch.nr,
+ card->name, stat);
+ print_hex_dump_bytes(card->log,
+ DUMP_PREFIX_OFFSET, p,
+ stat);
+ }
+ recv_Bchannel(&bc->bch, 0, false);
+ stat = bchannel_get_rxbuf(&bc->bch, bc->bch.maxlen);
+ if (stat < 0) {
+ pr_warning("%s.B%d: No memory for %d bytes\n",
+ card->name, bc->bch.nr, cnt);
+ return;
+ }
+ } else if (stat == -HDLC_CRC_ERROR) {
pr_info("%s: B%1d receive frame CRC error\n",
card->name, bc->bch.nr);
- else if (stat == -HDLC_FRAMING_ERROR)
+ } else if (stat == -HDLC_FRAMING_ERROR) {
pr_info("%s: B%1d receive framing error\n",
card->name, bc->bch.nr);
- else if (stat == -HDLC_LENGTH_ERROR)
+ } else if (stat == -HDLC_LENGTH_ERROR) {
pr_info("%s: B%1d receive frame too long (> %d)\n",
card->name, bc->bch.nr, bc->bch.maxlen);
- } else
- stat = cnt;
-
- if (stat > 0) {
- if (debug & DEBUG_HW_BFIFO) {
- snprintf(card->log, LOG_SIZE, "B%1d-recv %s %d ",
- bc->bch.nr, card->name, stat);
- print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET,
- p, stat);
}
- recv_Bchannel(&bc->bch, 0);
- }
- if (test_bit(FLG_HDLC, &bc->bch.Flags)) {
pn += i;
cnt -= i;
- if (!bc->bch.rx_skb) {
- bc->bch.rx_skb = mI_alloc_skb(bc->bch.maxlen,
- GFP_ATOMIC);
- if (!bc->bch.rx_skb) {
- pr_info("%s: B%1d receive out of memory\n",
- card->name, bc->bch.nr);
- return;
- }
- }
- if (cnt > 0)
- goto next_frame;
}
}
@@ -544,22 +537,31 @@ static void
fill_dma(struct tiger_ch *bc)
{
struct tiger_hw *card = bc->bch.hw;
- int count, i;
- u32 m, v;
+ int count, i, fillempty = 0;
+ u32 m, v, n = 0;
u8 *p;
if (bc->free == 0)
return;
- count = bc->bch.tx_skb->len - bc->bch.tx_idx;
- if (count <= 0)
- return;
- pr_debug("%s: %s B%1d %d/%d/%d/%d state %x idx %d/%d\n", card->name,
- __func__, bc->bch.nr, count, bc->free, bc->bch.tx_idx,
- bc->bch.tx_skb->len, bc->txstate, bc->idx, card->send.idx);
+ if (!bc->bch.tx_skb) {
+ if (!test_bit(FLG_TX_EMPTY, &bc->bch.Flags))
+ return;
+ fillempty = 1;
+ count = card->send.size >> 1;
+ p = bc->bch.fill;
+ } else {
+ count = bc->bch.tx_skb->len - bc->bch.tx_idx;
+ if (count <= 0)
+ return;
+ pr_debug("%s: %s B%1d %d/%d/%d/%d state %x idx %d/%d\n",
+ card->name, __func__, bc->bch.nr, count, bc->free,
+ bc->bch.tx_idx, bc->bch.tx_skb->len, bc->txstate,
+ bc->idx, card->send.idx);
+ p = bc->bch.tx_skb->data + bc->bch.tx_idx;
+ }
if (bc->txstate & (TX_IDLE | TX_INIT | TX_UNDERRUN))
resync(bc, card);
- p = bc->bch.tx_skb->data + bc->bch.tx_idx;
- if (test_bit(FLG_HDLC, &bc->bch.Flags)) {
+ if (test_bit(FLG_HDLC, &bc->bch.Flags) && !fillempty) {
count = isdnhdlc_encode(&bc->hsend, p, count, &i,
bc->hsbuf, bc->free);
pr_debug("%s: B%1d hdlc encoded %d in %d\n", card->name,
@@ -570,17 +572,33 @@ fill_dma(struct tiger_ch *bc)
} else {
if (count > bc->free)
count = bc->free;
- bc->bch.tx_idx += count;
+ if (!fillempty)
+ bc->bch.tx_idx += count;
bc->free -= count;
}
m = (bc->bch.nr & 1) ? 0xffffff00 : 0xffff00ff;
- for (i = 0; i < count; i++) {
- if (bc->idx >= card->send.size)
- bc->idx = 0;
- v = card->send.start[bc->idx];
- v &= m;
- v |= (bc->bch.nr & 1) ? (u32)(p[i]) : ((u32)(p[i])) << 8;
- card->send.start[bc->idx++] = v;
+ if (fillempty) {
+ n = p[0];
+ if (!(bc->bch.nr & 1))
+ n <<= 8;
+ for (i = 0; i < count; i++) {
+ if (bc->idx >= card->send.size)
+ bc->idx = 0;
+ v = card->send.start[bc->idx];
+ v &= m;
+ v |= n;
+ card->send.start[bc->idx++] = v;
+ }
+ } else {
+ for (i = 0; i < count; i++) {
+ if (bc->idx >= card->send.size)
+ bc->idx = 0;
+ v = card->send.start[bc->idx];
+ v &= m;
+ n = p[i];
+ v |= (bc->bch.nr & 1) ? n : n << 8;
+ card->send.start[bc->idx++] = v;
+ }
}
if (debug & DEBUG_HW_BFIFO) {
snprintf(card->log, LOG_SIZE, "B%1d-send %s %d ",
@@ -595,21 +613,26 @@ fill_dma(struct tiger_ch *bc)
static int
bc_next_frame(struct tiger_ch *bc)
{
- if (bc->bch.tx_skb && bc->bch.tx_idx < bc->bch.tx_skb->len)
+ int ret = 1;
+
+ if (bc->bch.tx_skb && bc->bch.tx_idx < bc->bch.tx_skb->len) {
fill_dma(bc);
- else {
- if (bc->bch.tx_skb) {
- /* send confirm, on trans, free on hdlc. */
- if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags))
- confirm_Bsend(&bc->bch);
+ } else {
+ if (bc->bch.tx_skb)
dev_kfree_skb(bc->bch.tx_skb);
- }
- if (get_next_bframe(&bc->bch))
+ if (get_next_bframe(&bc->bch)) {
fill_dma(bc);
- else
- return 0;
+ test_and_clear_bit(FLG_TX_EMPTY, &bc->bch.Flags);
+ } else if (test_bit(FLG_TX_EMPTY, &bc->bch.Flags)) {
+ fill_dma(bc);
+ } else if (test_bit(FLG_FILLEMPTY, &bc->bch.Flags)) {
+ test_and_set_bit(FLG_TX_EMPTY, &bc->bch.Flags);
+ ret = 0;
+ } else {
+ ret = 0;
+ }
}
- return 1;
+ return ret;
}
static void
@@ -732,22 +755,17 @@ nj_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
struct tiger_ch *bc = container_of(bch, struct tiger_ch, bch);
struct tiger_hw *card = bch->hw;
struct mISDNhead *hh = mISDN_HEAD_P(skb);
- u32 id;
- u_long flags;
+ unsigned long flags;
switch (hh->prim) {
case PH_DATA_REQ:
spin_lock_irqsave(&card->lock, flags);
ret = bchannel_senddata(bch, skb);
if (ret > 0) { /* direct TX */
- id = hh->id; /* skb can be freed */
fill_dma(bc);
ret = 0;
- spin_unlock_irqrestore(&card->lock, flags);
- if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
- queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
- } else
- spin_unlock_irqrestore(&card->lock, flags);
+ }
+ spin_unlock_irqrestore(&card->lock, flags);
return ret;
case PH_ACTIVATE_REQ:
spin_lock_irqsave(&card->lock, flags);
@@ -778,21 +796,7 @@ nj_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
static int
channel_bctrl(struct tiger_ch *bc, struct mISDN_ctrl_req *cq)
{
- int ret = 0;
- struct tiger_hw *card = bc->bch.hw;
-
- switch (cq->op) {
- case MISDN_CTRL_GETOP:
- cq->op = 0;
- break;
- /* Nothing implemented yet */
- case MISDN_CTRL_FILL_EMPTY:
- default:
- pr_info("%s: %s unknown Op %x\n", card->name, __func__, cq->op);
- ret = -EINVAL;
- break;
- }
- return ret;
+ return mISDN_ctrl_bchannel(&bc->bch, cq);
}
static int
@@ -808,14 +812,10 @@ nj_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
switch (cmd) {
case CLOSE_CHANNEL:
test_and_clear_bit(FLG_OPEN, &bch->Flags);
- if (test_bit(FLG_ACTIVE, &bch->Flags)) {
- spin_lock_irqsave(&card->lock, flags);
- mISDN_freebchannel(bch);
- test_and_clear_bit(FLG_TX_BUSY, &bch->Flags);
- test_and_clear_bit(FLG_ACTIVE, &bch->Flags);
- mode_tiger(bc, ISDN_P_NONE);
- spin_unlock_irqrestore(&card->lock, flags);
- }
+ spin_lock_irqsave(&card->lock, flags);
+ mISDN_freebchannel(bch);
+ mode_tiger(bc, ISDN_P_NONE);
+ spin_unlock_irqrestore(&card->lock, flags);
ch->protocol = ISDN_P_NONE;
ch->peer = NULL;
module_put(THIS_MODULE);
@@ -837,7 +837,7 @@ channel_ctrl(struct tiger_hw *card, struct mISDN_ctrl_req *cq)
switch (cq->op) {
case MISDN_CTRL_GETOP:
- cq->op = MISDN_CTRL_LOOP;
+ cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_L1_TIMER3;
break;
case MISDN_CTRL_LOOP:
/* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
@@ -847,6 +847,9 @@ channel_ctrl(struct tiger_hw *card, struct mISDN_ctrl_req *cq)
}
ret = card->isac.ctrl(&card->isac, HW_TESTLOOP, cq->channel);
break;
+ case MISDN_CTRL_L1_TIMER3:
+ ret = card->isac.ctrl(&card->isac, HW_TIMER3_VALUE, cq->p1);
+ break;
default:
pr_info("%s: %s unknown Op %x\n", card->name, __func__, cq->op);
ret = -EINVAL;
@@ -1027,7 +1030,8 @@ setup_instance(struct tiger_hw *card)
for (i = 0; i < 2; i++) {
card->bc[i].bch.nr = i + 1;
set_channelmap(i + 1, card->isac.dch.dev.channelmap);
- mISDN_initbchannel(&card->bc[i].bch, MAX_DATA_MEM);
+ mISDN_initbchannel(&card->bc[i].bch, MAX_DATA_MEM,
+ NJ_DMA_RXSIZE >> 1);
card->bc[i].bch.hw = card;
card->bc[i].bch.ch.send = nj_l2l1B;
card->bc[i].bch.ch.ctrl = nj_bctrl;
diff --git a/drivers/isdn/hardware/mISDN/speedfax.c b/drivers/isdn/hardware/mISDN/speedfax.c
index 04689935148b..93f344d74e54 100644
--- a/drivers/isdn/hardware/mISDN/speedfax.c
+++ b/drivers/isdn/hardware/mISDN/speedfax.c
@@ -224,7 +224,7 @@ channel_ctrl(struct sfax_hw *sf, struct mISDN_ctrl_req *cq)
switch (cq->op) {
case MISDN_CTRL_GETOP:
- cq->op = MISDN_CTRL_LOOP;
+ cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_L1_TIMER3;
break;
case MISDN_CTRL_LOOP:
/* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
@@ -234,6 +234,9 @@ channel_ctrl(struct sfax_hw *sf, struct mISDN_ctrl_req *cq)
}
ret = sf->isac.ctrl(&sf->isac, HW_TESTLOOP, cq->channel);
break;
+ case MISDN_CTRL_L1_TIMER3:
+ ret = sf->isac.ctrl(&sf->isac, HW_TIMER3_VALUE, cq->p1);
+ break;
default:
pr_info("%s: unknown Op %x\n", sf->name, cq->op);
ret = -EINVAL;
diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c
index 2183357f0799..26a86b846099 100644
--- a/drivers/isdn/hardware/mISDN/w6692.c
+++ b/drivers/isdn/hardware/mISDN/w6692.c
@@ -465,6 +465,7 @@ W6692_empty_Bfifo(struct w6692_ch *wch, int count)
{
struct w6692_hw *card = wch->bch.hw;
u8 *ptr;
+ int maxlen;
pr_debug("%s: empty_Bfifo %d\n", card->name, count);
if (unlikely(wch->bch.state == ISDN_P_NONE)) {
@@ -474,20 +475,18 @@ W6692_empty_Bfifo(struct w6692_ch *wch, int count)
skb_trim(wch->bch.rx_skb, 0);
return;
}
- if (!wch->bch.rx_skb) {
- wch->bch.rx_skb = mI_alloc_skb(wch->bch.maxlen, GFP_ATOMIC);
- if (unlikely(!wch->bch.rx_skb)) {
- pr_info("%s: B receive out of memory\n", card->name);
- WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK |
- W_B_CMDR_RACT);
- return;
- }
+ if (test_bit(FLG_RX_OFF, &wch->bch.Flags)) {
+ wch->bch.dropcnt += count;
+ WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
+ return;
}
- if (wch->bch.rx_skb->len + count > wch->bch.maxlen) {
- pr_debug("%s: empty_Bfifo incoming packet too large\n",
- card->name);
+ maxlen = bchannel_get_rxbuf(&wch->bch, count);
+ if (maxlen < 0) {
WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
- skb_trim(wch->bch.rx_skb, 0);
+ if (wch->bch.rx_skb)
+ skb_trim(wch->bch.rx_skb, 0);
+ pr_warning("%s.B%d: No bufferspace for %d bytes\n",
+ card->name, wch->bch.nr, count);
return;
}
ptr = skb_put(wch->bch.rx_skb, count);
@@ -504,16 +503,22 @@ static void
W6692_fill_Bfifo(struct w6692_ch *wch)
{
struct w6692_hw *card = wch->bch.hw;
- int count;
+ int count, fillempty = 0;
u8 *ptr, cmd = W_B_CMDR_RACT | W_B_CMDR_XMS;
pr_debug("%s: fill Bfifo\n", card->name);
- if (!wch->bch.tx_skb)
- return;
- count = wch->bch.tx_skb->len - wch->bch.tx_idx;
- if (count <= 0)
- return;
- ptr = wch->bch.tx_skb->data + wch->bch.tx_idx;
+ if (!wch->bch.tx_skb) {
+ if (!test_bit(FLG_TX_EMPTY, &wch->bch.Flags))
+ return;
+ ptr = wch->bch.fill;
+ count = W_B_FIFO_THRESH;
+ fillempty = 1;
+ } else {
+ count = wch->bch.tx_skb->len - wch->bch.tx_idx;
+ if (count <= 0)
+ return;
+ ptr = wch->bch.tx_skb->data + wch->bch.tx_idx;
+ }
if (count > W_B_FIFO_THRESH)
count = W_B_FIFO_THRESH;
else if (test_bit(FLG_HDLC, &wch->bch.Flags))
@@ -522,9 +527,16 @@ W6692_fill_Bfifo(struct w6692_ch *wch)
pr_debug("%s: fill Bfifo%d/%d\n", card->name,
count, wch->bch.tx_idx);
wch->bch.tx_idx += count;
- outsb(wch->addr + W_B_XFIFO, ptr, count);
+ if (fillempty) {
+ while (count > 0) {
+ outsb(wch->addr + W_B_XFIFO, ptr, MISDN_BCH_FILL_SIZE);
+ count -= MISDN_BCH_FILL_SIZE;
+ }
+ } else {
+ outsb(wch->addr + W_B_XFIFO, ptr, count);
+ }
WriteW6692B(wch, W_B_CMDR, cmd);
- if (debug & DEBUG_HW_DFIFO) {
+ if ((debug & DEBUG_HW_BFIFO) && !fillempty) {
snprintf(card->log, 63, "B%1d-send %s %d ",
wch->bch.nr, card->name, count);
print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, ptr, count);
@@ -638,17 +650,17 @@ w6692_mode(struct w6692_ch *wch, u32 pr)
static void
send_next(struct w6692_ch *wch)
{
- if (wch->bch.tx_skb && wch->bch.tx_idx < wch->bch.tx_skb->len)
+ if (wch->bch.tx_skb && wch->bch.tx_idx < wch->bch.tx_skb->len) {
W6692_fill_Bfifo(wch);
- else {
- if (wch->bch.tx_skb) {
- /* send confirm, on trans, free on hdlc. */
- if (test_bit(FLG_TRANSPARENT, &wch->bch.Flags))
- confirm_Bsend(&wch->bch);
+ } else {
+ if (wch->bch.tx_skb)
dev_kfree_skb(wch->bch.tx_skb);
- }
- if (get_next_bframe(&wch->bch))
+ if (get_next_bframe(&wch->bch)) {
+ W6692_fill_Bfifo(wch);
+ test_and_clear_bit(FLG_TX_EMPTY, &wch->bch.Flags);
+ } else if (test_bit(FLG_TX_EMPTY, &wch->bch.Flags)) {
W6692_fill_Bfifo(wch);
+ }
}
}
@@ -698,7 +710,7 @@ W6692B_interrupt(struct w6692_hw *card, int ch)
if (count == 0)
count = W_B_FIFO_THRESH;
W6692_empty_Bfifo(wch, count);
- recv_Bchannel(&wch->bch, 0);
+ recv_Bchannel(&wch->bch, 0, false);
}
}
if (stat & W_B_EXI_RMR) {
@@ -714,9 +726,8 @@ W6692B_interrupt(struct w6692_hw *card, int ch)
W_B_CMDR_RRST | W_B_CMDR_RACT);
} else {
W6692_empty_Bfifo(wch, W_B_FIFO_THRESH);
- if (test_bit(FLG_TRANSPARENT, &wch->bch.Flags) &&
- wch->bch.rx_skb && (wch->bch.rx_skb->len > 0))
- recv_Bchannel(&wch->bch, 0);
+ if (test_bit(FLG_TRANSPARENT, &wch->bch.Flags))
+ recv_Bchannel(&wch->bch, 0, false);
}
}
if (stat & W_B_EXI_RDOV) {
@@ -738,8 +749,8 @@ W6692B_interrupt(struct w6692_hw *card, int ch)
wch->bch.nr, star);
}
if (star & W_B_STAR_XDOW) {
- pr_debug("%s: B%d XDOW proto=%x\n", card->name,
- wch->bch.nr, wch->bch.state);
+ pr_warning("%s: B%d XDOW proto=%x\n", card->name,
+ wch->bch.nr, wch->bch.state);
#ifdef ERROR_STATISTIC
wch->bch.err_xdu++;
#endif
@@ -752,20 +763,21 @@ W6692B_interrupt(struct w6692_hw *card, int ch)
}
}
send_next(wch);
- if (stat & W_B_EXI_XDUN)
+ if (star & W_B_STAR_XDOW)
return; /* handle XDOW only once */
}
if (stat & W_B_EXI_XDUN) {
- pr_debug("%s: B%d XDUN proto=%x\n", card->name,
- wch->bch.nr, wch->bch.state);
+ pr_warning("%s: B%d XDUN proto=%x\n", card->name,
+ wch->bch.nr, wch->bch.state);
#ifdef ERROR_STATISTIC
wch->bch.err_xdu++;
#endif
- WriteW6692B(wch, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT);
- /* resend */
+ /* resend - no XRST needed */
if (wch->bch.tx_skb) {
if (!test_bit(FLG_TRANSPARENT, &wch->bch.Flags))
wch->bch.tx_idx = 0;
+ } else if (test_bit(FLG_FILLEMPTY, &wch->bch.Flags)) {
+ test_and_set_bit(FLG_TX_EMPTY, &wch->bch.Flags);
}
send_next(wch);
}
@@ -944,22 +956,17 @@ w6692_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
struct w6692_hw *card = bch->hw;
int ret = -EINVAL;
struct mISDNhead *hh = mISDN_HEAD_P(skb);
- u32 id;
- u_long flags;
+ unsigned long flags;
switch (hh->prim) {
case PH_DATA_REQ:
spin_lock_irqsave(&card->lock, flags);
ret = bchannel_senddata(bch, skb);
if (ret > 0) { /* direct TX */
- id = hh->id; /* skb can be freed */
ret = 0;
W6692_fill_Bfifo(bc);
- spin_unlock_irqrestore(&card->lock, flags);
- if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
- queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
- } else
- spin_unlock_irqrestore(&card->lock, flags);
+ }
+ spin_unlock_irqrestore(&card->lock, flags);
return ret;
case PH_ACTIVATE_REQ:
spin_lock_irqsave(&card->lock, flags);
@@ -994,20 +1001,7 @@ w6692_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
static int
channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
{
- int ret = 0;
-
- switch (cq->op) {
- case MISDN_CTRL_GETOP:
- cq->op = 0;
- break;
- /* Nothing implemented yet */
- case MISDN_CTRL_FILL_EMPTY:
- default:
- pr_info("%s: unknown Op %x\n", __func__, cq->op);
- ret = -EINVAL;
- break;
- }
- return ret;
+ return mISDN_ctrl_bchannel(bch, cq);
}
static int
@@ -1022,7 +1016,6 @@ open_bchannel(struct w6692_hw *card, struct channel_req *rq)
bch = &card->bc[rq->adr.channel - 1].bch;
if (test_and_set_bit(FLG_OPEN, &bch->Flags))
return -EBUSY; /* b-channel can be only open once */
- test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
bch->ch.protocol = rq->protocol;
rq->ch = &bch->ch;
return 0;
@@ -1035,7 +1028,10 @@ channel_ctrl(struct w6692_hw *card, struct mISDN_ctrl_req *cq)
switch (cq->op) {
case MISDN_CTRL_GETOP:
- cq->op = 0;
+ cq->op = MISDN_CTRL_L1_TIMER3;
+ break;
+ case MISDN_CTRL_L1_TIMER3:
+ ret = l1_event(card->dch.l1, HW_TIMER3_VALUE | (cq->p1 & 0xff));
break;
default:
pr_info("%s: unknown CTRL OP %x\n", card->name, cq->op);
@@ -1058,15 +1054,10 @@ w6692_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
switch (cmd) {
case CLOSE_CHANNEL:
test_and_clear_bit(FLG_OPEN, &bch->Flags);
- if (test_bit(FLG_ACTIVE, &bch->Flags)) {
- spin_lock_irqsave(&card->lock, flags);
- mISDN_freebchannel(bch);
- w6692_mode(bc, ISDN_P_NONE);
- spin_unlock_irqrestore(&card->lock, flags);
- } else {
- skb_queue_purge(&bch->rqueue);
- bch->rcount = 0;
- }
+ spin_lock_irqsave(&card->lock, flags);
+ mISDN_freebchannel(bch);
+ w6692_mode(bc, ISDN_P_NONE);
+ spin_unlock_irqrestore(&card->lock, flags);
ch->protocol = ISDN_P_NONE;
ch->peer = NULL;
module_put(THIS_MODULE);
@@ -1320,7 +1311,8 @@ setup_instance(struct w6692_hw *card)
card->dch.hw = card;
card->dch.dev.nrbchan = 2;
for (i = 0; i < 2; i++) {
- mISDN_initbchannel(&card->bc[i].bch, MAX_DATA_MEM);
+ mISDN_initbchannel(&card->bc[i].bch, MAX_DATA_MEM,
+ W_B_FIFO_THRESH);
card->bc[i].bch.hw = card;
card->bc[i].bch.nr = i + 1;
card->bc[i].bch.ch.nr = i + 1;
diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c
index ba91333e3e41..88e4f0ee073c 100644
--- a/drivers/isdn/hysdn/hysdn_proclog.c
+++ b/drivers/isdn/hysdn/hysdn_proclog.c
@@ -156,17 +156,9 @@ static ssize_t
hysdn_log_write(struct file *file, const char __user *buf, size_t count, loff_t *off)
{
int rc;
- unsigned char valbuf[128];
hysdn_card *card = file->private_data;
- if (count > (sizeof(valbuf) - 1))
- count = sizeof(valbuf) - 1; /* limit length */
- if (copy_from_user(valbuf, buf, count))
- return (-EFAULT); /* copy failed */
-
- valbuf[count] = 0; /* terminating 0 */
-
- rc = kstrtoul(valbuf, 0, &card->debug_flags);
+ rc = kstrtoul_from_user(buf, count, 0, &card->debug_flags);
if (rc < 0)
return rc;
hysdn_addlog(card, "debug set to 0x%lx", card->debug_flags);
diff --git a/drivers/isdn/i4l/isdn_bsdcomp.c b/drivers/isdn/i4l/isdn_bsdcomp.c
index c59e8d2c0675..8837ac5a492d 100644
--- a/drivers/isdn/i4l/isdn_bsdcomp.c
+++ b/drivers/isdn/i4l/isdn_bsdcomp.c
@@ -612,7 +612,7 @@ static int bsd_compress(void *state, struct sk_buff *skb_in, struct sk_buff *skb
db->n_bits++;
/* If output length is too large then this is an incompressible frame. */
- if (!skb_out || (skb_out && skb_out->len >= skb_in->len)) {
+ if (!skb_out || skb_out->len >= skb_in->len) {
++db->incomp_count;
db->incomp_bytes += isize;
return 0;
diff --git a/drivers/isdn/mISDN/core.c b/drivers/isdn/mISDN/core.c
index a24530f05db0..c401634c00ec 100644
--- a/drivers/isdn/mISDN/core.c
+++ b/drivers/isdn/mISDN/core.c
@@ -355,6 +355,22 @@ mISDN_unregister_Bprotocol(struct Bprotocol *bp)
}
EXPORT_SYMBOL(mISDN_unregister_Bprotocol);
+static const char *msg_no_channel = "<no channel>";
+static const char *msg_no_stack = "<no stack>";
+static const char *msg_no_stackdev = "<no stack device>";
+
+const char *mISDNDevName4ch(struct mISDNchannel *ch)
+{
+ if (!ch)
+ return msg_no_channel;
+ if (!ch->st)
+ return msg_no_stack;
+ if (!ch->st->dev)
+ return msg_no_stackdev;
+ return dev_name(&ch->st->dev->dev);
+};
+EXPORT_SYMBOL(mISDNDevName4ch);
+
static int
mISDNInit(void)
{
diff --git a/drivers/isdn/mISDN/dsp.h b/drivers/isdn/mISDN/dsp.h
index afe4173ae007..fc1733a08845 100644
--- a/drivers/isdn/mISDN/dsp.h
+++ b/drivers/isdn/mISDN/dsp.h
@@ -76,7 +76,9 @@ extern u8 dsp_silence;
#define MAX_SECONDS_JITTER_CHECK 5
extern struct timer_list dsp_spl_tl;
-extern u32 dsp_spl_jiffies;
+
+/* the datatype need to match jiffies datatype */
+extern unsigned long dsp_spl_jiffies;
/* the structure of conferences:
*
diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c
index 334feab060a1..a4f05c54c32b 100644
--- a/drivers/isdn/mISDN/dsp_cmx.c
+++ b/drivers/isdn/mISDN/dsp_cmx.c
@@ -742,8 +742,8 @@ dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp)
member->dsp->pcm_slot_tx,
member->dsp->pcm_bank_tx,
member->dsp->pcm_bank_rx);
- conf->hardware = 0;
- conf->software = 1;
+ conf->hardware = 1;
+ conf->software = tx_data;
return;
}
/* find a new slot */
@@ -834,8 +834,8 @@ dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp)
nextm->dsp->name,
member->dsp->pcm_slot_tx,
member->dsp->pcm_slot_rx);
- conf->hardware = 0;
- conf->software = 1;
+ conf->hardware = 1;
+ conf->software = tx_data;
return;
}
/* find two new slot */
@@ -939,8 +939,11 @@ dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp)
/* for more than two members.. */
/* if all members already have the same conference */
- if (all_conf)
+ if (all_conf) {
+ conf->hardware = 1;
+ conf->software = tx_data;
return;
+ }
/*
* if there is an existing conference, but not all members have joined
@@ -1013,6 +1016,8 @@ dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp)
dsp_cmx_hw_message(member->dsp,
MISDN_CTRL_HFC_CONF_JOIN, current_conf, 0, 0, 0);
}
+ conf->hardware = 1;
+ conf->software = tx_data;
return;
}
@@ -1328,7 +1333,7 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members)
}
if (dsp->conf && dsp->conf->software && dsp->conf->hardware)
tx_data_only = 1;
- if (dsp->conf->software && dsp->echo.hardware)
+ if (dsp->echo.software && dsp->echo.hardware)
tx_data_only = 1;
}
@@ -1619,7 +1624,7 @@ send_packet:
static u32 jittercount; /* counter for jitter check */
struct timer_list dsp_spl_tl;
-u32 dsp_spl_jiffies; /* calculate the next time to fire */
+unsigned long dsp_spl_jiffies; /* calculate the next time to fire */
static u16 dsp_count; /* last sample count */
static int dsp_count_valid; /* if we have last sample count */
diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c
index 2ac2d7a25a9f..28c99c623bcd 100644
--- a/drivers/isdn/mISDN/dsp_core.c
+++ b/drivers/isdn/mISDN/dsp_core.c
@@ -268,6 +268,7 @@ dsp_fill_empty(struct dsp *dsp)
}
cq.op = MISDN_CTRL_FILL_EMPTY;
cq.p1 = 1;
+ cq.p2 = dsp_silence;
if (dsp->ch.peer->ctrl(dsp->ch.peer, CONTROL_CHANNEL, &cq)) {
printk(KERN_DEBUG "%s: CONTROL_CHANNEL failed\n",
__func__);
diff --git a/drivers/isdn/mISDN/dsp_dtmf.c b/drivers/isdn/mISDN/dsp_dtmf.c
index 887860bdc63b..642f30be5ce2 100644
--- a/drivers/isdn/mISDN/dsp_dtmf.c
+++ b/drivers/isdn/mISDN/dsp_dtmf.c
@@ -222,16 +222,25 @@ coefficients:
goto storedigit;
}
- if (dsp_debug & DEBUG_DSP_DTMFCOEFF)
+ if (dsp_debug & DEBUG_DSP_DTMFCOEFF) {
+ s32 tresh_100 = tresh/100;
+
+ if (tresh_100 == 0) {
+ tresh_100 = 1;
+ printk(KERN_DEBUG
+ "tresh(%d) too small set tresh/100 to 1\n",
+ tresh);
+ }
printk(KERN_DEBUG "a %3d %3d %3d %3d %3d %3d %3d %3d"
" tr:%3d r %3d %3d %3d %3d %3d %3d %3d %3d\n",
result[0] / 10000, result[1] / 10000, result[2] / 10000,
result[3] / 10000, result[4] / 10000, result[5] / 10000,
result[6] / 10000, result[7] / 10000, tresh / 10000,
- result[0] / (tresh / 100), result[1] / (tresh / 100),
- result[2] / (tresh / 100), result[3] / (tresh / 100),
- result[4] / (tresh / 100), result[5] / (tresh / 100),
- result[6] / (tresh / 100), result[7] / (tresh / 100));
+ result[0] / (tresh_100), result[1] / (tresh_100),
+ result[2] / (tresh_100), result[3] / (tresh_100),
+ result[4] / (tresh_100), result[5] / (tresh_100),
+ result[6] / (tresh_100), result[7] / (tresh_100));
+ }
/* calc digit (lowgroup/highgroup) */
lowgroup = -1;
diff --git a/drivers/isdn/mISDN/hwchannel.c b/drivers/isdn/mISDN/hwchannel.c
index c74c363554c4..ef34fd40867c 100644
--- a/drivers/isdn/mISDN/hwchannel.c
+++ b/drivers/isdn/mISDN/hwchannel.c
@@ -81,10 +81,16 @@ mISDN_initdchannel(struct dchannel *ch, int maxlen, void *phf)
EXPORT_SYMBOL(mISDN_initdchannel);
int
-mISDN_initbchannel(struct bchannel *ch, int maxlen)
+mISDN_initbchannel(struct bchannel *ch, unsigned short maxlen,
+ unsigned short minlen)
{
ch->Flags = 0;
+ ch->minlen = minlen;
+ ch->next_minlen = minlen;
+ ch->init_minlen = minlen;
ch->maxlen = maxlen;
+ ch->next_maxlen = maxlen;
+ ch->init_maxlen = maxlen;
ch->hw = NULL;
ch->rx_skb = NULL;
ch->tx_skb = NULL;
@@ -134,6 +140,14 @@ mISDN_clear_bchannel(struct bchannel *ch)
test_and_clear_bit(FLG_TX_BUSY, &ch->Flags);
test_and_clear_bit(FLG_TX_NEXT, &ch->Flags);
test_and_clear_bit(FLG_ACTIVE, &ch->Flags);
+ test_and_clear_bit(FLG_FILLEMPTY, &ch->Flags);
+ test_and_clear_bit(FLG_TX_EMPTY, &ch->Flags);
+ test_and_clear_bit(FLG_RX_OFF, &ch->Flags);
+ ch->dropcnt = 0;
+ ch->minlen = ch->init_minlen;
+ ch->next_minlen = ch->init_minlen;
+ ch->maxlen = ch->init_maxlen;
+ ch->next_maxlen = ch->init_maxlen;
}
EXPORT_SYMBOL(mISDN_clear_bchannel);
@@ -148,6 +162,51 @@ mISDN_freebchannel(struct bchannel *ch)
}
EXPORT_SYMBOL(mISDN_freebchannel);
+int
+mISDN_ctrl_bchannel(struct bchannel *bch, struct mISDN_ctrl_req *cq)
+{
+ int ret = 0;
+
+ switch (cq->op) {
+ case MISDN_CTRL_GETOP:
+ cq->op = MISDN_CTRL_RX_BUFFER | MISDN_CTRL_FILL_EMPTY |
+ MISDN_CTRL_RX_OFF;
+ break;
+ case MISDN_CTRL_FILL_EMPTY:
+ if (cq->p1) {
+ memset(bch->fill, cq->p2 & 0xff, MISDN_BCH_FILL_SIZE);
+ test_and_set_bit(FLG_FILLEMPTY, &bch->Flags);
+ } else {
+ test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
+ }
+ break;
+ case MISDN_CTRL_RX_OFF:
+ /* read back dropped byte count */
+ cq->p2 = bch->dropcnt;
+ if (cq->p1)
+ test_and_set_bit(FLG_RX_OFF, &bch->Flags);
+ else
+ test_and_clear_bit(FLG_RX_OFF, &bch->Flags);
+ bch->dropcnt = 0;
+ break;
+ case MISDN_CTRL_RX_BUFFER:
+ if (cq->p2 > MISDN_CTRL_RX_SIZE_IGNORE)
+ bch->next_maxlen = cq->p2;
+ if (cq->p1 > MISDN_CTRL_RX_SIZE_IGNORE)
+ bch->next_minlen = cq->p1;
+ /* we return the old values */
+ cq->p1 = bch->minlen;
+ cq->p2 = bch->maxlen;
+ break;
+ default:
+ pr_info("mISDN unhandled control %x operation\n", cq->op);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+EXPORT_SYMBOL(mISDN_ctrl_bchannel);
+
static inline u_int
get_sapi_tei(u_char *p)
{
@@ -197,24 +256,37 @@ recv_Echannel(struct dchannel *ech, struct dchannel *dch)
EXPORT_SYMBOL(recv_Echannel);
void
-recv_Bchannel(struct bchannel *bch, unsigned int id)
+recv_Bchannel(struct bchannel *bch, unsigned int id, bool force)
{
struct mISDNhead *hh;
- hh = mISDN_HEAD_P(bch->rx_skb);
- hh->prim = PH_DATA_IND;
- hh->id = id;
- if (bch->rcount >= 64) {
- printk(KERN_WARNING "B-channel %p receive queue overflow, "
- "flushing!\n", bch);
- skb_queue_purge(&bch->rqueue);
- bch->rcount = 0;
+ /* if allocation did fail upper functions still may call us */
+ if (unlikely(!bch->rx_skb))
return;
+ if (unlikely(!bch->rx_skb->len)) {
+ /* we have no data to send - this may happen after recovery
+ * from overflow or too small allocation.
+ * We need to free the buffer here */
+ dev_kfree_skb(bch->rx_skb);
+ bch->rx_skb = NULL;
+ } else {
+ if (test_bit(FLG_TRANSPARENT, &bch->Flags) &&
+ (bch->rx_skb->len < bch->minlen) && !force)
+ return;
+ hh = mISDN_HEAD_P(bch->rx_skb);
+ hh->prim = PH_DATA_IND;
+ hh->id = id;
+ if (bch->rcount >= 64) {
+ printk(KERN_WARNING
+ "B%d receive queue overflow - flushing!\n",
+ bch->nr);
+ skb_queue_purge(&bch->rqueue);
+ }
+ bch->rcount++;
+ skb_queue_tail(&bch->rqueue, bch->rx_skb);
+ bch->rx_skb = NULL;
+ schedule_event(bch, FLG_RECVQUEUE);
}
- bch->rcount++;
- skb_queue_tail(&bch->rqueue, bch->rx_skb);
- bch->rx_skb = NULL;
- schedule_event(bch, FLG_RECVQUEUE);
}
EXPORT_SYMBOL(recv_Bchannel);
@@ -272,7 +344,7 @@ get_next_dframe(struct dchannel *dch)
}
EXPORT_SYMBOL(get_next_dframe);
-void
+static void
confirm_Bsend(struct bchannel *bch)
{
struct sk_buff *skb;
@@ -294,7 +366,6 @@ confirm_Bsend(struct bchannel *bch)
skb_queue_tail(&bch->rqueue, skb);
schedule_event(bch, FLG_RECVQUEUE);
}
-EXPORT_SYMBOL(confirm_Bsend);
int
get_next_bframe(struct bchannel *bch)
@@ -305,8 +376,8 @@ get_next_bframe(struct bchannel *bch)
if (bch->tx_skb) {
bch->next_skb = NULL;
test_and_clear_bit(FLG_TX_NEXT, &bch->Flags);
- if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
- confirm_Bsend(bch); /* not for transparent */
+ /* confirm imediately to allow next data */
+ confirm_Bsend(bch);
return 1;
} else {
test_and_clear_bit(FLG_TX_NEXT, &bch->Flags);
@@ -395,7 +466,62 @@ bchannel_senddata(struct bchannel *ch, struct sk_buff *skb)
/* write to fifo */
ch->tx_skb = skb;
ch->tx_idx = 0;
+ confirm_Bsend(ch);
return 1;
}
}
EXPORT_SYMBOL(bchannel_senddata);
+
+/* The function allocates a new receive skb on demand with a size for the
+ * requirements of the current protocol. It returns the tailroom of the
+ * receive skb or an error.
+ */
+int
+bchannel_get_rxbuf(struct bchannel *bch, int reqlen)
+{
+ int len;
+
+ if (bch->rx_skb) {
+ len = skb_tailroom(bch->rx_skb);
+ if (len < reqlen) {
+ pr_warning("B%d no space for %d (only %d) bytes\n",
+ bch->nr, reqlen, len);
+ if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {
+ /* send what we have now and try a new buffer */
+ recv_Bchannel(bch, 0, true);
+ } else {
+ /* on HDLC we have to drop too big frames */
+ return -EMSGSIZE;
+ }
+ } else {
+ return len;
+ }
+ }
+ /* update current min/max length first */
+ if (unlikely(bch->maxlen != bch->next_maxlen))
+ bch->maxlen = bch->next_maxlen;
+ if (unlikely(bch->minlen != bch->next_minlen))
+ bch->minlen = bch->next_minlen;
+ if (unlikely(reqlen > bch->maxlen))
+ return -EMSGSIZE;
+ if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {
+ if (reqlen >= bch->minlen) {
+ len = reqlen;
+ } else {
+ len = 2 * bch->minlen;
+ if (len > bch->maxlen)
+ len = bch->maxlen;
+ }
+ } else {
+ /* with HDLC we do not know the length yet */
+ len = bch->maxlen;
+ }
+ bch->rx_skb = mI_alloc_skb(len, GFP_ATOMIC);
+ if (!bch->rx_skb) {
+ pr_warning("B%d receive no memory for %d bytes\n",
+ bch->nr, len);
+ len = -ENOMEM;
+ }
+ return len;
+}
+EXPORT_SYMBOL(bchannel_get_rxbuf);
diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c
index 0f88acf1185f..db50f788855d 100644
--- a/drivers/isdn/mISDN/l1oip_core.c
+++ b/drivers/isdn/mISDN/l1oip_core.c
@@ -1420,7 +1420,7 @@ init_card(struct l1oip *hc, int pri, int bundle)
bch->nr = i + ch;
bch->slot = i + ch;
bch->debug = debug;
- mISDN_initbchannel(bch, MAX_DATA_MEM);
+ mISDN_initbchannel(bch, MAX_DATA_MEM, 0);
bch->hw = hc;
bch->ch.send = handle_bmsg;
bch->ch.ctrl = l1oip_bctrl;
diff --git a/drivers/isdn/mISDN/layer1.c b/drivers/isdn/mISDN/layer1.c
index 0fc49b375514..bebc57b72138 100644
--- a/drivers/isdn/mISDN/layer1.c
+++ b/drivers/isdn/mISDN/layer1.c
@@ -28,13 +28,15 @@ static u_int *debug;
struct layer1 {
u_long Flags;
struct FsmInst l1m;
- struct FsmTimer timer;
+ struct FsmTimer timer3;
+ struct FsmTimer timerX;
int delay;
+ int t3_value;
struct dchannel *dch;
dchannel_l1callback *dcb;
};
-#define TIMER3_VALUE 7000
+#define TIMER3_DEFAULT_VALUE 7000
static
struct Fsm l1fsm_s = {NULL, 0, 0, NULL, NULL};
@@ -134,7 +136,7 @@ l1_deact_req_s(struct FsmInst *fi, int event, void *arg)
struct layer1 *l1 = fi->userdata;
mISDN_FsmChangeState(fi, ST_L1_F3);
- mISDN_FsmRestartTimer(&l1->timer, 550, EV_TIMER_DEACT, NULL, 2);
+ mISDN_FsmRestartTimer(&l1->timerX, 550, EV_TIMER_DEACT, NULL, 2);
test_and_set_bit(FLG_L1_DEACTTIMER, &l1->Flags);
}
@@ -179,11 +181,11 @@ l1_info4_ind(struct FsmInst *fi, int event, void *arg)
mISDN_FsmChangeState(fi, ST_L1_F7);
l1->dcb(l1->dch, INFO3_P8);
if (test_and_clear_bit(FLG_L1_DEACTTIMER, &l1->Flags))
- mISDN_FsmDelTimer(&l1->timer, 4);
+ mISDN_FsmDelTimer(&l1->timerX, 4);
if (!test_bit(FLG_L1_ACTIVATED, &l1->Flags)) {
if (test_and_clear_bit(FLG_L1_T3RUN, &l1->Flags))
- mISDN_FsmDelTimer(&l1->timer, 3);
- mISDN_FsmRestartTimer(&l1->timer, 110, EV_TIMER_ACT, NULL, 2);
+ mISDN_FsmDelTimer(&l1->timer3, 3);
+ mISDN_FsmRestartTimer(&l1->timerX, 110, EV_TIMER_ACT, NULL, 2);
test_and_set_bit(FLG_L1_ACTTIMER, &l1->Flags);
}
}
@@ -201,7 +203,7 @@ l1_timer3(struct FsmInst *fi, int event, void *arg)
}
if (l1->l1m.state != ST_L1_F6) {
mISDN_FsmChangeState(fi, ST_L1_F3);
- l1->dcb(l1->dch, HW_POWERUP_REQ);
+ /* do not force anything here, we need send INFO 0 */
}
}
@@ -233,8 +235,9 @@ l1_activate_s(struct FsmInst *fi, int event, void *arg)
{
struct layer1 *l1 = fi->userdata;
- mISDN_FsmRestartTimer(&l1->timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
+ mISDN_FsmRestartTimer(&l1->timer3, l1->t3_value, EV_TIMER3, NULL, 2);
test_and_set_bit(FLG_L1_T3RUN, &l1->Flags);
+ /* Tell HW to send INFO 1 */
l1->dcb(l1->dch, HW_RESET_REQ);
}
@@ -302,7 +305,8 @@ static struct FsmNode L1SFnList[] =
static void
release_l1(struct layer1 *l1) {
- mISDN_FsmDelTimer(&l1->timer, 0);
+ mISDN_FsmDelTimer(&l1->timerX, 0);
+ mISDN_FsmDelTimer(&l1->timer3, 0);
if (l1->dch)
l1->dch->l1 = NULL;
module_put(THIS_MODULE);
@@ -356,6 +360,16 @@ l1_event(struct layer1 *l1, u_int event)
release_l1(l1);
break;
default:
+ if ((event & ~HW_TIMER3_VMASK) == HW_TIMER3_VALUE) {
+ int val = event & HW_TIMER3_VMASK;
+
+ if (val < 5)
+ val = 5;
+ if (val > 30)
+ val = 30;
+ l1->t3_value = val;
+ break;
+ }
if (*debug & DEBUG_L1)
printk(KERN_DEBUG "%s %x unhandled\n",
__func__, event);
@@ -377,13 +391,15 @@ create_l1(struct dchannel *dch, dchannel_l1callback *dcb) {
nl1->l1m.fsm = &l1fsm_s;
nl1->l1m.state = ST_L1_F3;
nl1->Flags = 0;
+ nl1->t3_value = TIMER3_DEFAULT_VALUE;
nl1->l1m.debug = *debug & DEBUG_L1_FSM;
nl1->l1m.userdata = nl1;
nl1->l1m.userint = 0;
nl1->l1m.printdebug = l1m_debug;
nl1->dch = dch;
nl1->dcb = dcb;
- mISDN_FsmInitTimer(&nl1->l1m, &nl1->timer);
+ mISDN_FsmInitTimer(&nl1->l1m, &nl1->timer3);
+ mISDN_FsmInitTimer(&nl1->l1m, &nl1->timerX);
__module_get(THIS_MODULE);
dch->l1 = nl1;
return 0;
diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c
index 39d7375fa551..0dc8abca1407 100644
--- a/drivers/isdn/mISDN/layer2.c
+++ b/drivers/isdn/mISDN/layer2.c
@@ -58,6 +58,8 @@ enum {
EV_L1_DEACTIVATE,
EV_L2_T200,
EV_L2_T203,
+ EV_L2_T200I,
+ EV_L2_T203I,
EV_L2_SET_OWN_BUSY,
EV_L2_CLEAR_OWN_BUSY,
EV_L2_FRAME_ERROR,
@@ -86,6 +88,8 @@ static char *strL2Event[] =
"EV_L1_DEACTIVATE",
"EV_L2_T200",
"EV_L2_T203",
+ "EV_L2_T200I",
+ "EV_L2_T203I",
"EV_L2_SET_OWN_BUSY",
"EV_L2_CLEAR_OWN_BUSY",
"EV_L2_FRAME_ERROR",
@@ -106,8 +110,8 @@ l2m_debug(struct FsmInst *fi, char *fmt, ...)
vaf.fmt = fmt;
vaf.va = &va;
- printk(KERN_DEBUG "l2 (sapi %d tei %d): %pV\n",
- l2->sapi, l2->tei, &vaf);
+ printk(KERN_DEBUG "%s l2 (sapi %d tei %d): %pV\n",
+ mISDNDevName4ch(&l2->ch), l2->sapi, l2->tei, &vaf);
va_end(va);
}
@@ -150,7 +154,8 @@ l2up(struct layer2 *l2, u_int prim, struct sk_buff *skb)
mISDN_HEAD_ID(skb) = (l2->ch.nr << 16) | l2->ch.addr;
err = l2->up->send(l2->up, skb);
if (err) {
- printk(KERN_WARNING "%s: err=%d\n", __func__, err);
+ printk(KERN_WARNING "%s: dev %s err=%d\n", __func__,
+ mISDNDevName4ch(&l2->ch), err);
dev_kfree_skb(skb);
}
}
@@ -174,7 +179,8 @@ l2up_create(struct layer2 *l2, u_int prim, int len, void *arg)
memcpy(skb_put(skb, len), arg, len);
err = l2->up->send(l2->up, skb);
if (err) {
- printk(KERN_WARNING "%s: err=%d\n", __func__, err);
+ printk(KERN_WARNING "%s: dev %s err=%d\n", __func__,
+ mISDNDevName4ch(&l2->ch), err);
dev_kfree_skb(skb);
}
}
@@ -185,7 +191,8 @@ l2down_skb(struct layer2 *l2, struct sk_buff *skb) {
ret = l2->ch.recv(l2->ch.peer, skb);
if (ret && (*debug & DEBUG_L2_RECV))
- printk(KERN_DEBUG "l2down_skb: ret(%d)\n", ret);
+ printk(KERN_DEBUG "l2down_skb: dev %s ret(%d)\n",
+ mISDNDevName4ch(&l2->ch), ret);
return ret;
}
@@ -276,12 +283,37 @@ ph_data_confirm(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb) {
return ret;
}
+static void
+l2_timeout(struct FsmInst *fi, int event, void *arg)
+{
+ struct layer2 *l2 = fi->userdata;
+ struct sk_buff *skb;
+ struct mISDNhead *hh;
+
+ skb = mI_alloc_skb(0, GFP_ATOMIC);
+ if (!skb) {
+ printk(KERN_WARNING "%s: L2(%d,%d) nr:%x timer %s no skb\n",
+ mISDNDevName4ch(&l2->ch), l2->sapi, l2->tei,
+ l2->ch.nr, event == EV_L2_T200 ? "T200" : "T203");
+ return;
+ }
+ hh = mISDN_HEAD_P(skb);
+ hh->prim = event == EV_L2_T200 ? DL_TIMER200_IND : DL_TIMER203_IND;
+ hh->id = l2->ch.nr;
+ if (*debug & DEBUG_TIMER)
+ printk(KERN_DEBUG "%s: L2(%d,%d) nr:%x timer %s expired\n",
+ mISDNDevName4ch(&l2->ch), l2->sapi, l2->tei,
+ l2->ch.nr, event == EV_L2_T200 ? "T200" : "T203");
+ if (l2->ch.st)
+ l2->ch.st->own.recv(&l2->ch.st->own, skb);
+}
+
static int
l2mgr(struct layer2 *l2, u_int prim, void *arg) {
long c = (long)arg;
- printk(KERN_WARNING
- "l2mgr: addr:%x prim %x %c\n", l2->id, prim, (char)c);
+ printk(KERN_WARNING "l2mgr: dev %s addr:%x prim %x %c\n",
+ mISDNDevName4ch(&l2->ch), l2->id, prim, (char)c);
if (test_bit(FLG_LAPD, &l2->flag) &&
!test_bit(FLG_FIXED_TEI, &l2->flag)) {
switch (c) {
@@ -603,8 +635,8 @@ send_uframe(struct layer2 *l2, struct sk_buff *skb, u_char cmd, u_char cr)
else {
skb = mI_alloc_skb(i, GFP_ATOMIC);
if (!skb) {
- printk(KERN_WARNING "%s: can't alloc skbuff\n",
- __func__);
+ printk(KERN_WARNING "%s: can't alloc skbuff in %s\n",
+ mISDNDevName4ch(&l2->ch), __func__);
return;
}
}
@@ -1089,8 +1121,8 @@ enquiry_cr(struct layer2 *l2, u_char typ, u_char cr, u_char pf)
tmp[i++] = (l2->vr << 5) | typ | (pf ? 0x10 : 0);
skb = mI_alloc_skb(i, GFP_ATOMIC);
if (!skb) {
- printk(KERN_WARNING
- "isdnl2 can't alloc sbbuff for enquiry_cr\n");
+ printk(KERN_WARNING "%s: isdnl2 can't alloc sbbuff in %s\n",
+ mISDNDevName4ch(&l2->ch), __func__);
return;
}
memcpy(skb_put(skb, i), tmp, i);
@@ -1150,7 +1182,7 @@ invoke_retransmission(struct layer2 *l2, unsigned int nr)
else
printk(KERN_WARNING
"%s: windowar[%d] is NULL\n",
- __func__, p1);
+ mISDNDevName4ch(&l2->ch), p1);
l2->windowar[p1] = NULL;
}
mISDN_FsmEvent(&l2->l2m, EV_L2_ACK_PULL, NULL);
@@ -1461,8 +1493,8 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
p1 = (l2->vs - l2->va) % 8;
p1 = (p1 + l2->sow) % l2->window;
if (l2->windowar[p1]) {
- printk(KERN_WARNING "isdnl2 try overwrite ack queue entry %d\n",
- p1);
+ printk(KERN_WARNING "%s: l2 try overwrite ack queue entry %d\n",
+ mISDNDevName4ch(&l2->ch), p1);
dev_kfree_skb(l2->windowar[p1]);
}
l2->windowar[p1] = skb;
@@ -1482,12 +1514,14 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
memcpy(skb_push(nskb, i), header, i);
else {
printk(KERN_WARNING
- "isdnl2 pull_iqueue skb header(%d/%d) too short\n", i, p1);
+ "%s: L2 pull_iqueue skb header(%d/%d) too short\n",
+ mISDNDevName4ch(&l2->ch), i, p1);
oskb = nskb;
nskb = mI_alloc_skb(oskb->len + i, GFP_ATOMIC);
if (!nskb) {
dev_kfree_skb(oskb);
- printk(KERN_WARNING "%s: no skb mem\n", __func__);
+ printk(KERN_WARNING "%s: no skb mem in %s\n",
+ mISDNDevName4ch(&l2->ch), __func__);
return;
}
memcpy(skb_put(nskb, i), header, i);
@@ -1814,11 +1848,16 @@ static struct FsmNode L2FnList[] =
{ST_L2_8, EV_L2_SUPER, l2_st8_got_super},
{ST_L2_7, EV_L2_I, l2_got_iframe},
{ST_L2_8, EV_L2_I, l2_got_iframe},
- {ST_L2_5, EV_L2_T200, l2_st5_tout_200},
- {ST_L2_6, EV_L2_T200, l2_st6_tout_200},
- {ST_L2_7, EV_L2_T200, l2_st7_tout_200},
- {ST_L2_8, EV_L2_T200, l2_st8_tout_200},
- {ST_L2_7, EV_L2_T203, l2_st7_tout_203},
+ {ST_L2_5, EV_L2_T200, l2_timeout},
+ {ST_L2_6, EV_L2_T200, l2_timeout},
+ {ST_L2_7, EV_L2_T200, l2_timeout},
+ {ST_L2_8, EV_L2_T200, l2_timeout},
+ {ST_L2_7, EV_L2_T203, l2_timeout},
+ {ST_L2_5, EV_L2_T200I, l2_st5_tout_200},
+ {ST_L2_6, EV_L2_T200I, l2_st6_tout_200},
+ {ST_L2_7, EV_L2_T200I, l2_st7_tout_200},
+ {ST_L2_8, EV_L2_T200I, l2_st8_tout_200},
+ {ST_L2_7, EV_L2_T203I, l2_st7_tout_203},
{ST_L2_7, EV_L2_ACK_PULL, l2_pull_iqueue},
{ST_L2_7, EV_L2_SET_OWN_BUSY, l2_set_own_busy},
{ST_L2_8, EV_L2_SET_OWN_BUSY, l2_set_own_busy},
@@ -1858,7 +1897,8 @@ ph_data_indication(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb)
ptei = *datap++;
if ((psapi & 1) || !(ptei & 1)) {
printk(KERN_WARNING
- "l2 D-channel frame wrong EA0/EA1\n");
+ "%s l2 D-channel frame wrong EA0/EA1\n",
+ mISDNDevName4ch(&l2->ch));
return ret;
}
psapi >>= 2;
@@ -1867,7 +1907,8 @@ ph_data_indication(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb)
/* not our business */
if (*debug & DEBUG_L2)
printk(KERN_DEBUG "%s: sapi %d/%d mismatch\n",
- __func__, psapi, l2->sapi);
+ mISDNDevName4ch(&l2->ch), psapi,
+ l2->sapi);
dev_kfree_skb(skb);
return 0;
}
@@ -1875,7 +1916,7 @@ ph_data_indication(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb)
/* not our business */
if (*debug & DEBUG_L2)
printk(KERN_DEBUG "%s: tei %d/%d mismatch\n",
- __func__, ptei, l2->tei);
+ mISDNDevName4ch(&l2->ch), ptei, l2->tei);
dev_kfree_skb(skb);
return 0;
}
@@ -1916,7 +1957,8 @@ ph_data_indication(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb)
} else
c = 'L';
if (c) {
- printk(KERN_WARNING "l2 D-channel frame error %c\n", c);
+ printk(KERN_WARNING "%s:l2 D-channel frame error %c\n",
+ mISDNDevName4ch(&l2->ch), c);
mISDN_FsmEvent(&l2->l2m, EV_L2_FRAME_ERROR, (void *)(long)c);
}
return ret;
@@ -1930,8 +1972,17 @@ l2_send(struct mISDNchannel *ch, struct sk_buff *skb)
int ret = -EINVAL;
if (*debug & DEBUG_L2_RECV)
- printk(KERN_DEBUG "%s: prim(%x) id(%x) sapi(%d) tei(%d)\n",
- __func__, hh->prim, hh->id, l2->sapi, l2->tei);
+ printk(KERN_DEBUG "%s: %s prim(%x) id(%x) sapi(%d) tei(%d)\n",
+ __func__, mISDNDevName4ch(&l2->ch), hh->prim, hh->id,
+ l2->sapi, l2->tei);
+ if (hh->prim == DL_INTERN_MSG) {
+ struct mISDNhead *chh = hh + 1; /* saved copy */
+
+ *hh = *chh;
+ if (*debug & DEBUG_L2_RECV)
+ printk(KERN_DEBUG "%s: prim(%x) id(%x) internal msg\n",
+ mISDNDevName4ch(&l2->ch), hh->prim, hh->id);
+ }
switch (hh->prim) {
case PH_DATA_IND:
ret = ph_data_indication(l2, hh, skb);
@@ -1987,6 +2038,12 @@ l2_send(struct mISDNchannel *ch, struct sk_buff *skb)
ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DL_RELEASE_REQ,
skb);
break;
+ case DL_TIMER200_IND:
+ mISDN_FsmEvent(&l2->l2m, EV_L2_T200I, NULL);
+ break;
+ case DL_TIMER203_IND:
+ mISDN_FsmEvent(&l2->l2m, EV_L2_T203I, NULL);
+ break;
default:
if (*debug & DEBUG_L2)
l2m_debug(&l2->l2m, "l2 unknown pr %04x",
@@ -2005,7 +2062,8 @@ tei_l2(struct layer2 *l2, u_int cmd, u_long arg)
int ret = -EINVAL;
if (*debug & DEBUG_L2_TEI)
- printk(KERN_DEBUG "%s: cmd(%x)\n", __func__, cmd);
+ printk(KERN_DEBUG "%s: cmd(%x) in %s\n",
+ mISDNDevName4ch(&l2->ch), cmd, __func__);
switch (cmd) {
case (MDL_ASSIGN_REQ):
ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_ASSIGN, (void *)arg);
@@ -2018,7 +2076,8 @@ tei_l2(struct layer2 *l2, u_int cmd, u_long arg)
break;
case (MDL_ERROR_RSP):
/* ETS 300-125 5.3.2.1 Test: TC13010 */
- printk(KERN_NOTICE "MDL_ERROR|REQ (tei_l2)\n");
+ printk(KERN_NOTICE "%s: MDL_ERROR|REQ (tei_l2)\n",
+ mISDNDevName4ch(&l2->ch));
ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_ERROR, NULL);
break;
}
@@ -2050,7 +2109,8 @@ l2_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
u_int info;
if (*debug & DEBUG_L2_CTRL)
- printk(KERN_DEBUG "%s:(%x)\n", __func__, cmd);
+ printk(KERN_DEBUG "%s: %s cmd(%x)\n",
+ mISDNDevName4ch(ch), __func__, cmd);
switch (cmd) {
case OPEN_CHANNEL:
diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c
index ba2bc0c776e2..be88728f1106 100644
--- a/drivers/isdn/mISDN/tei.c
+++ b/drivers/isdn/mISDN/tei.c
@@ -790,18 +790,23 @@ tei_ph_data_ind(struct teimgr *tm, u_int mt, u_char *dp, int len)
static struct layer2 *
create_new_tei(struct manager *mgr, int tei, int sapi)
{
- u_long opt = 0;
- u_long flags;
- int id;
- struct layer2 *l2;
+ unsigned long opt = 0;
+ unsigned long flags;
+ int id;
+ struct layer2 *l2;
+ struct channel_req rq;
if (!mgr->up)
return NULL;
if ((tei >= 0) && (tei < 64))
test_and_set_bit(OPTION_L2_FIXEDTEI, &opt);
- if (mgr->ch.st->dev->Dprotocols
- & ((1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1)))
+ if (mgr->ch.st->dev->Dprotocols & ((1 << ISDN_P_TE_E1) |
+ (1 << ISDN_P_NT_E1))) {
test_and_set_bit(OPTION_L2_PMX, &opt);
+ rq.protocol = ISDN_P_NT_E1;
+ } else {
+ rq.protocol = ISDN_P_NT_S0;
+ }
l2 = create_l2(mgr->up, ISDN_P_LAPD_NT, opt, tei, sapi);
if (!l2) {
printk(KERN_WARNING "%s:no memory for layer2\n", __func__);
@@ -836,6 +841,14 @@ create_new_tei(struct manager *mgr, int tei, int sapi)
l2->ch.recv = mgr->ch.recv;
l2->ch.peer = mgr->ch.peer;
l2->ch.ctrl(&l2->ch, OPEN_CHANNEL, NULL);
+ /* We need open here L1 for the manager as well (refcounting) */
+ rq.adr.dev = mgr->ch.st->dev->id;
+ id = mgr->ch.st->own.ctrl(&mgr->ch.st->own, OPEN_CHANNEL, &rq);
+ if (id < 0) {
+ printk(KERN_WARNING "%s: cannot open L1\n", __func__);
+ l2->ch.ctrl(&l2->ch, CLOSE_CHANNEL, NULL);
+ l2 = NULL;
+ }
}
return l2;
}
@@ -978,10 +991,11 @@ TEIrelease(struct layer2 *l2)
static int
create_teimgr(struct manager *mgr, struct channel_req *crq)
{
- struct layer2 *l2;
- u_long opt = 0;
- u_long flags;
- int id;
+ struct layer2 *l2;
+ unsigned long opt = 0;
+ unsigned long flags;
+ int id;
+ struct channel_req l1rq;
if (*debug & DEBUG_L2_TEI)
printk(KERN_DEBUG "%s: %s proto(%x) adr(%d %d %d %d)\n",
@@ -1016,6 +1030,7 @@ create_teimgr(struct manager *mgr, struct channel_req *crq)
if (crq->protocol == ISDN_P_LAPD_TE)
test_and_set_bit(MGR_OPT_USER, &mgr->options);
}
+ l1rq.adr = crq->adr;
if (mgr->ch.st->dev->Dprotocols
& ((1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1)))
test_and_set_bit(OPTION_L2_PMX, &opt);
@@ -1023,6 +1038,8 @@ create_teimgr(struct manager *mgr, struct channel_req *crq)
mgr->up = crq->ch;
id = DL_INFO_L2_CONNECT;
teiup_create(mgr, DL_INFORMATION_IND, sizeof(id), &id);
+ if (test_bit(MGR_PH_ACTIVE, &mgr->options))
+ teiup_create(mgr, PH_ACTIVATE_IND, 0, NULL);
crq->ch = NULL;
if (!list_empty(&mgr->layer2)) {
read_lock_irqsave(&mgr->lock, flags);
@@ -1053,24 +1070,34 @@ create_teimgr(struct manager *mgr, struct channel_req *crq)
l2->tm->tei_m.fsm = &teifsmu;
l2->tm->tei_m.state = ST_TEI_NOP;
l2->tm->tval = 1000; /* T201 1 sec */
+ if (test_bit(OPTION_L2_PMX, &opt))
+ l1rq.protocol = ISDN_P_TE_E1;
+ else
+ l1rq.protocol = ISDN_P_TE_S0;
} else {
l2->tm->tei_m.fsm = &teifsmn;
l2->tm->tei_m.state = ST_TEI_NOP;
l2->tm->tval = 2000; /* T202 2 sec */
+ if (test_bit(OPTION_L2_PMX, &opt))
+ l1rq.protocol = ISDN_P_NT_E1;
+ else
+ l1rq.protocol = ISDN_P_NT_S0;
}
mISDN_FsmInitTimer(&l2->tm->tei_m, &l2->tm->timer);
write_lock_irqsave(&mgr->lock, flags);
id = get_free_id(mgr);
list_add_tail(&l2->list, &mgr->layer2);
write_unlock_irqrestore(&mgr->lock, flags);
- if (id < 0) {
- l2->ch.ctrl(&l2->ch, CLOSE_CHANNEL, NULL);
- } else {
+ if (id >= 0) {
l2->ch.nr = id;
l2->up->nr = id;
crq->ch = &l2->ch;
- id = 0;
+ /* We need open here L1 for the manager as well (refcounting) */
+ id = mgr->ch.st->own.ctrl(&mgr->ch.st->own, OPEN_CHANNEL,
+ &l1rq);
}
+ if (id < 0)
+ l2->ch.ctrl(&l2->ch, CLOSE_CHANNEL, NULL);
return id;
}
@@ -1096,12 +1123,16 @@ mgr_send(struct mISDNchannel *ch, struct sk_buff *skb)
break;
case PH_ACTIVATE_IND:
test_and_set_bit(MGR_PH_ACTIVE, &mgr->options);
+ if (mgr->up)
+ teiup_create(mgr, PH_ACTIVATE_IND, 0, NULL);
mISDN_FsmEvent(&mgr->deact, EV_ACTIVATE_IND, NULL);
do_send(mgr);
ret = 0;
break;
case PH_DEACTIVATE_IND:
test_and_clear_bit(MGR_PH_ACTIVE, &mgr->options);
+ if (mgr->up)
+ teiup_create(mgr, PH_DEACTIVATE_IND, 0, NULL);
mISDN_FsmEvent(&mgr->deact, EV_DEACTIVATE_IND, NULL);
ret = 0;
break;
@@ -1263,7 +1294,7 @@ static int
mgr_bcast(struct mISDNchannel *ch, struct sk_buff *skb)
{
struct manager *mgr = container_of(ch, struct manager, bcast);
- struct mISDNhead *hh = mISDN_HEAD_P(skb);
+ struct mISDNhead *hhc, *hh = mISDN_HEAD_P(skb);
struct sk_buff *cskb = NULL;
struct layer2 *l2;
u_long flags;
@@ -1278,10 +1309,17 @@ mgr_bcast(struct mISDNchannel *ch, struct sk_buff *skb)
skb = NULL;
} else {
if (!cskb)
- cskb = skb_copy(skb, GFP_KERNEL);
+ cskb = skb_copy(skb, GFP_ATOMIC);
}
if (cskb) {
- ret = l2->ch.send(&l2->ch, cskb);
+ hhc = mISDN_HEAD_P(cskb);
+ /* save original header behind normal header */
+ hhc++;
+ *hhc = *hh;
+ hhc--;
+ hhc->prim = DL_INTERN_MSG;
+ hhc->id = l2->ch.nr;
+ ret = ch->st->own.recv(&ch->st->own, cskb);
if (ret) {
if (*debug & DEBUG_SEND_ERR)
printk(KERN_DEBUG