All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] mISDN: Collection of patches for layer1/layer2
@ 2012-04-28 11:43 Karsten Keil
  2012-04-28 11:43 ` [PATCH 1/8] mISDN: Added PH_* state info to tei manager Karsten Keil
                   ` (7 more replies)
  0 siblings, 8 replies; 14+ messages in thread
From: Karsten Keil @ 2012-04-28 11:43 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

These patches are mainly the outcome of a TBR3 recertification done
within BT labs.
The patches itself are very well tested more as 10000 valid/invalid
call setup were done in preparartion for the TBR3 aproval.

For net-next.


Andreas Eversberg (1):
  mISDN: Added PH_* state info to tei manager.

Karsten Keil (7):
  mISDN: Fix refcounting bug
  Sometimes the ISDN chip only controls the D-channel
  mISDN: L2 timeouts need to be queued as L2 event
  mISDN: Make layer1 timer 3 value configurable
  mISDN: Layer1 statemachine fix
  mISDN: Help to identify the card
  mISDN: Add 2MBit mode for HFC E1 card

 drivers/isdn/hardware/mISDN/hfc_multi.h |   79 +++---
 drivers/isdn/hardware/mISDN/hfcmulti.c  |  426 ++++++++++++++++++++++++++-----
 drivers/isdn/mISDN/core.c               |   16 ++
 drivers/isdn/mISDN/layer1.c             |   37 ++-
 drivers/isdn/mISDN/layer2.c             |  119 +++++++---
 drivers/isdn/mISDN/socket.c             |    3 +
 drivers/isdn/mISDN/tei.c                |   71 ++++--
 include/linux/mISDNhw.h                 |    6 +
 include/linux/mISDNif.h                 |   71 ++++--
 9 files changed, 649 insertions(+), 179 deletions(-)

-- 
1.7.3.4

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/8] mISDN: Added PH_* state info to tei manager.
  2012-04-28 11:43 [PATCH 0/8] mISDN: Collection of patches for layer1/layer2 Karsten Keil
@ 2012-04-28 11:43 ` Karsten Keil
  2012-04-28 11:43 ` [PATCH 2/8] mISDN: Fix refcounting bug Karsten Keil
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Karsten Keil @ 2012-04-28 11:43 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Andreas Eversberg

From: Andreas Eversberg <andreas@eversberg.eu>

Tei manager reports current layer 1 state on creation.
On state change it reports it to the socket interface.

Signed-off-by: Andreas Eversberg <andreas@eversberg.eu>
Signed-off-by: Karsten Keil <keil@b1-systems.de>
---
 drivers/isdn/mISDN/tei.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c
index ba2bc0c..969766f 100644
--- a/drivers/isdn/mISDN/tei.c
+++ b/drivers/isdn/mISDN/tei.c
@@ -1023,6 +1023,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);
@@ -1096,12 +1098,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;
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/8] mISDN: Fix refcounting bug
  2012-04-28 11:43 [PATCH 0/8] mISDN: Collection of patches for layer1/layer2 Karsten Keil
  2012-04-28 11:43 ` [PATCH 1/8] mISDN: Added PH_* state info to tei manager Karsten Keil
@ 2012-04-28 11:43 ` Karsten Keil
  2012-04-28 11:43 ` [PATCH 3/8] Sometimes the ISDN chip only controls the D-channel Karsten Keil
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Karsten Keil @ 2012-04-28 11:43 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Karsten Keil

From: Karsten Keil <isdn@linux-pingi.de>

Under some configs it was still not possible to unload the driver,
because the module use count was srewed up.

Signed-off-by: Karsten Keil <keil@b1-systems.de>
---
 drivers/isdn/mISDN/tei.c |   52 +++++++++++++++++++++++++++++++++------------
 1 files changed, 38 insertions(+), 14 deletions(-)

diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c
index 969766f..25ed826 100644
--- a/drivers/isdn/mISDN/tei.c
+++ b/drivers/isdn/mISDN/tei.c
@@ -790,18 +790,22 @@ 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;
+	u_long			opt = 0;
+	u_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 +840,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 +990,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;
+	u_long			opt = 0;
+	u_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 +1029,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);
@@ -1055,24 +1069,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;
 }
 
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 3/8] Sometimes the ISDN chip only controls the D-channel
  2012-04-28 11:43 [PATCH 0/8] mISDN: Collection of patches for layer1/layer2 Karsten Keil
  2012-04-28 11:43 ` [PATCH 1/8] mISDN: Added PH_* state info to tei manager Karsten Keil
  2012-04-28 11:43 ` [PATCH 2/8] mISDN: Fix refcounting bug Karsten Keil
@ 2012-04-28 11:43 ` Karsten Keil
  2012-05-01 17:30   ` David Miller
  2012-04-28 11:43 ` [PATCH 4/8] mISDN: L2 timeouts need to be queued as L2 event Karsten Keil
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 14+ messages in thread
From: Karsten Keil @ 2012-04-28 11:43 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

The B-channels are only accessed via the PCM backplane.
Add infrastruckture for this special mode.

Signed-off-by: Karsten Keil <kkeil@linux-pingi.de>
---
 drivers/isdn/mISDN/socket.c |    3 +++
 include/linux/mISDNhw.h     |    3 +++
 include/linux/mISDNif.h     |   13 +++++++++----
 3 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
index abe2d69..502bcf1 100644
--- a/drivers/isdn/mISDN/socket.c
+++ b/drivers/isdn/mISDN/socket.c
@@ -270,6 +270,7 @@ data_sock_release(struct socket *sock)
 		break;
 	case ISDN_P_LAPD_TE:
 	case ISDN_P_LAPD_NT:
+	case ISDN_P_B_PCM:
 	case ISDN_P_B_RAW:
 	case ISDN_P_B_HDLC:
 	case ISDN_P_B_X75SLP:
@@ -544,6 +545,7 @@ data_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
 		err = create_l2entity(_pms(sk)->dev, &_pms(sk)->ch,
 				      sk->sk_protocol, maddr);
 		break;
+	case ISDN_P_B_PCM:
 	case ISDN_P_B_RAW:
 	case ISDN_P_B_HDLC:
 	case ISDN_P_B_X75SLP:
@@ -800,6 +802,7 @@ mISDN_sock_create(struct net *net, struct socket *sock, int proto, int kern)
 	case ISDN_P_NT_E1:
 	case ISDN_P_LAPD_TE:
 	case ISDN_P_LAPD_NT:
+	case ISDN_P_B_PCM:
 	case ISDN_P_B_RAW:
 	case ISDN_P_B_HDLC:
 	case ISDN_P_B_X75SLP:
diff --git a/include/linux/mISDNhw.h b/include/linux/mISDNhw.h
index 4af8414..74d5734 100644
--- a/include/linux/mISDNhw.h
+++ b/include/linux/mISDNhw.h
@@ -5,6 +5,7 @@
  *   Basic declarations for the mISDN HW channels
  *
  * Copyright 2008  by Karsten Keil <kkeil@novell.com>
+ * Copyright 2009-2012  by Karsten Keil <kkeil@linux-pingi.de>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -148,6 +149,8 @@ struct bchannel {
 	u_int			state;
 	void			*hw;
 	int			slot;	/* multiport card channel slot */
+	int			pcm_tx;	/* PCM tx slot nr */
+	int			pcm_rx;	/* PCM rx slot nr */
 	struct timer_list	timer;
 	/* receive data */
 	struct sk_buff		*rx_skb;
diff --git a/include/linux/mISDNif.h b/include/linux/mISDNif.h
index b5e7f22..bdda647 100644
--- a/include/linux/mISDNif.h
+++ b/include/linux/mISDNif.h
@@ -37,7 +37,7 @@
  */
 #define	MISDN_MAJOR_VERSION	1
 #define	MISDN_MINOR_VERSION	1
-#define MISDN_RELEASE		21
+#define MISDN_RELEASE		24
 
 /* primitives for information exchange
  * generell format
@@ -229,7 +229,7 @@
 
 #define ISDN_P_B_MASK		0x1f
 #define ISDN_P_B_START		0x20
-
+#define ISDN_P_B_PCM		0x20
 #define ISDN_P_B_RAW		0x21
 #define ISDN_P_B_HDLC		0x22
 #define ISDN_P_B_X75SLP		0x23
@@ -360,8 +360,8 @@ clear_channelmap(u_int nr, u_char *map)
 #define MISDN_CTRL_LOOP			0x0001
 #define MISDN_CTRL_CONNECT		0x0002
 #define MISDN_CTRL_DISCONNECT		0x0004
-#define MISDN_CTRL_PCMCONNECT		0x0010
-#define MISDN_CTRL_PCMDISCONNECT	0x0020
+#define MISDN_CTRL_GET_PCM_SLOTS	0x0010
+#define MISDN_CTRL_SET_PCM_SLOTS	0x0020
 #define MISDN_CTRL_SETPEER		0x0040
 #define MISDN_CTRL_UNSETPEER		0x0080
 #define MISDN_CTRL_RX_OFF		0x0100
@@ -381,6 +381,10 @@ clear_channelmap(u_int nr, u_char *map)
 #define MISDN_CTRL_HFC_WD_INIT		0x4009
 #define MISDN_CTRL_HFC_WD_RESET		0x400A
 
+/* special PCM slot numbers */
+#define MISDN_PCM_SLOT_DISABLE	-1	/* PCM disabled */
+#define MISDN_PCM_SLOT_IGNORE	-2	/* PCM setting will be not changed */
+
 /* socket options */
 #define MISDN_TIME_STAMP		0x0001
 
@@ -389,6 +393,7 @@ struct mISDN_ctrl_req {
 	int		channel;
 	int		p1;
 	int		p2;
+	int		p3;
 };
 
 /* muxer options */
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 4/8] mISDN: L2 timeouts need to be queued as L2 event
  2012-04-28 11:43 [PATCH 0/8] mISDN: Collection of patches for layer1/layer2 Karsten Keil
                   ` (2 preceding siblings ...)
  2012-04-28 11:43 ` [PATCH 3/8] Sometimes the ISDN chip only controls the D-channel Karsten Keil
@ 2012-04-28 11:43 ` Karsten Keil
  2012-04-28 11:43 ` [PATCH 5/8] mISDN: Make layer1 timer 3 value configurable Karsten Keil
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Karsten Keil @ 2012-04-28 11:43 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Karsten Keil

From: Karsten Keil <isdn@linux-pingi.de>

To be full preemptiv safe, we cannot handle a L2 timeout in the timer
context itself, we should do all actions via the D-channel thread.

Signed-off-by: Karsten Keil <kkeil@linux-pingi.de>
---
 drivers/isdn/mISDN/layer2.c |   58 +++++++++++++++++++++++++++++++++++++++---
 drivers/isdn/mISDN/tei.c    |   13 +++++++--
 include/linux/mISDNif.h     |    9 ++++++-
 3 files changed, 71 insertions(+), 9 deletions(-)

diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c
index 39d7375..d421495 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",
@@ -276,6 +280,31 @@ 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 "L2(%d,%d) nr:%x timer %s lost - no skb\n",
+			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 "L2(%d,%d) nr:%x timer %s expired\n",
+			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;
@@ -1814,11 +1843,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},
@@ -1932,6 +1966,14 @@ l2_send(struct mISDNchannel *ch, struct sk_buff *skb)
 	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);
+	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",
+				__func__, hh->prim, hh->id);
+	}
 	switch (hh->prim) {
 	case PH_DATA_IND:
 		ret = ph_data_indication(l2, hh, skb);
@@ -1987,6 +2029,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",
diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c
index 25ed826..c7f6bea 100644
--- a/drivers/isdn/mISDN/tei.c
+++ b/drivers/isdn/mISDN/tei.c
@@ -1293,7 +1293,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;
@@ -1308,10 +1308,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
diff --git a/include/linux/mISDNif.h b/include/linux/mISDNif.h
index bdda647..b7457e8 100644
--- a/include/linux/mISDNif.h
+++ b/include/linux/mISDNif.h
@@ -37,7 +37,7 @@
  */
 #define	MISDN_MAJOR_VERSION	1
 #define	MISDN_MINOR_VERSION	1
-#define MISDN_RELEASE		24
+#define MISDN_RELEASE		26
 
 /* primitives for information exchange
  * generell format
@@ -115,6 +115,11 @@
 #define MDL_ERROR_IND		0x1F04
 #define MDL_ERROR_RSP		0x5F04
 
+/* intern layer 2 */
+#define DL_TIMER200_IND		0x7004
+#define DL_TIMER203_IND		0x7304
+#define DL_INTERN_MSG		0x7804
+
 /* DL_INFORMATION_IND types */
 #define DL_INFO_L2_CONNECT	0x0001
 #define DL_INFO_L2_REMOVED	0x0002
@@ -289,6 +294,8 @@ struct mISDNversion {
 	unsigned short	release;
 };
 
+#define MAX_DEVICE_ID 63
+
 struct mISDN_devinfo {
 	u_int			id;
 	u_int			Dprotocols;
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 5/8] mISDN: Make layer1 timer 3 value configurable
  2012-04-28 11:43 [PATCH 0/8] mISDN: Collection of patches for layer1/layer2 Karsten Keil
                   ` (3 preceding siblings ...)
  2012-04-28 11:43 ` [PATCH 4/8] mISDN: L2 timeouts need to be queued as L2 event Karsten Keil
@ 2012-04-28 11:43 ` Karsten Keil
  2012-04-28 11:43 ` [PATCH 6/8] mISDN: Layer1 statemachine fix Karsten Keil
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Karsten Keil @ 2012-04-28 11:43 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Karsten Keil

From: Karsten Keil <isdn@linux-pingi.de>

For certification test it is very useful to change the layer1
timer3 value on runtime.

Signed-off-by: Karsten Keil <kkeil@linux-pingi.de>
---
 drivers/isdn/mISDN/layer1.c |   16 ++++++++++++++--
 include/linux/mISDNhw.h     |    3 +++
 include/linux/mISDNif.h     |    3 ++-
 3 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/isdn/mISDN/layer1.c b/drivers/isdn/mISDN/layer1.c
index 0fc49b3..ff05153 100644
--- a/drivers/isdn/mISDN/layer1.c
+++ b/drivers/isdn/mISDN/layer1.c
@@ -30,11 +30,12 @@ struct layer1 {
 	struct FsmInst l1m;
 	struct FsmTimer timer;
 	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};
@@ -233,7 +234,7 @@ 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->timer, l1->t3_value, EV_TIMER3, NULL, 2);
 	test_and_set_bit(FLG_L1_T3RUN, &l1->Flags);
 	l1->dcb(l1->dch, HW_RESET_REQ);
 }
@@ -356,6 +357,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,6 +388,7 @@ 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;
diff --git a/include/linux/mISDNhw.h b/include/linux/mISDNhw.h
index 74d5734..7075753 100644
--- a/include/linux/mISDNhw.h
+++ b/include/linux/mISDNhw.h
@@ -136,6 +136,9 @@ extern int	create_l1(struct dchannel *, dchannel_l1callback *);
 #define HW_TESTRX_RAW	0x9602
 #define HW_TESTRX_HDLC	0x9702
 #define HW_TESTRX_OFF	0x9802
+#define HW_TIMER3_IND	0x9902
+#define HW_TIMER3_VALUE	0x9a00
+#define HW_TIMER3_VMASK	0x00FF
 
 struct layer1;
 extern int	l1_event(struct layer1 *, u_int);
diff --git a/include/linux/mISDNif.h b/include/linux/mISDNif.h
index b7457e8..322d316 100644
--- a/include/linux/mISDNif.h
+++ b/include/linux/mISDNif.h
@@ -37,7 +37,7 @@
  */
 #define	MISDN_MAJOR_VERSION	1
 #define	MISDN_MINOR_VERSION	1
-#define MISDN_RELEASE		26
+#define MISDN_RELEASE		27
 
 /* primitives for information exchange
  * generell format
@@ -374,6 +374,7 @@ clear_channelmap(u_int nr, u_char *map)
 #define MISDN_CTRL_RX_OFF		0x0100
 #define MISDN_CTRL_FILL_EMPTY		0x0200
 #define MISDN_CTRL_GETPEER		0x0400
+#define MISDN_CTRL_L1_TIMER3		0x0800
 #define MISDN_CTRL_HW_FEATURES_OP	0x2000
 #define MISDN_CTRL_HW_FEATURES		0x2001
 #define MISDN_CTRL_HFC_OP		0x4000
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 6/8] mISDN: Layer1 statemachine fix
  2012-04-28 11:43 [PATCH 0/8] mISDN: Collection of patches for layer1/layer2 Karsten Keil
                   ` (4 preceding siblings ...)
  2012-04-28 11:43 ` [PATCH 5/8] mISDN: Make layer1 timer 3 value configurable Karsten Keil
@ 2012-04-28 11:43 ` Karsten Keil
  2012-04-28 11:43 ` [PATCH 7/8] mISDN: Help to identify the card Karsten Keil
  2012-04-28 11:43 ` [PATCH 8/8] mISDN: Add 2MBit mode for HFC E1 card Karsten Keil
  7 siblings, 0 replies; 14+ messages in thread
From: Karsten Keil @ 2012-04-28 11:43 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Karsten Keil

From: Karsten Keil <isdn@linux-pingi.de>

The timer3 and the activation delay timer need to be
independent.
Now layer1 pass TBR3 again.

Signed-off-by: Karsten Keil <kkeil@linux-pingi.de>
---
 drivers/isdn/mISDN/layer1.c |   23 ++++++++++++++---------
 1 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/isdn/mISDN/layer1.c b/drivers/isdn/mISDN/layer1.c
index ff05153..ee16e03 100644
--- a/drivers/isdn/mISDN/layer1.c
+++ b/drivers/isdn/mISDN/layer1.c
@@ -28,7 +28,8 @@ 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;
@@ -135,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);
 }
 
@@ -180,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,8 +202,9 @@ l1_timer3(struct FsmInst *fi, int event, void *arg)
 		l1->dcb(l1->dch, PH_DEACTIVATE_IND);
 	}
 	if (l1->l1m.state != ST_L1_F6) {
+		/* keep in F6 */
 		mISDN_FsmChangeState(fi, ST_L1_F3);
-		l1->dcb(l1->dch, HW_POWERUP_REQ);
+		/* do not force anything here, we need send INFO 0 */
 	}
 }
 
@@ -234,8 +236,9 @@ l1_activate_s(struct FsmInst *fi, int event, void *arg)
 {
 	struct layer1 *l1 = fi->userdata;
 
-	mISDN_FsmRestartTimer(&l1->timer, l1->t3_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);
 }
 
@@ -303,7 +306,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);
@@ -395,7 +399,8 @@ create_l1(struct dchannel *dch, dchannel_l1callback *dcb) {
 	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;
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 7/8] mISDN: Help to identify the card
  2012-04-28 11:43 [PATCH 0/8] mISDN: Collection of patches for layer1/layer2 Karsten Keil
                   ` (5 preceding siblings ...)
  2012-04-28 11:43 ` [PATCH 6/8] mISDN: Layer1 statemachine fix Karsten Keil
@ 2012-04-28 11:43 ` Karsten Keil
  2012-04-28 11:43 ` [PATCH 8/8] mISDN: Add 2MBit mode for HFC E1 card Karsten Keil
  7 siblings, 0 replies; 14+ messages in thread
From: Karsten Keil @ 2012-04-28 11:43 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Karsten Keil

From: Karsten Keil <isdn@linux-pingi.de>

With multiple cards is hard to figure out which port caused trouble
int the layer2 routines (e.g. got a timeout).
Now we have the informations in the log output.

Signed-off-by: Karsten Keil <kkeil@linux-pingi.de>
---
 drivers/isdn/mISDN/core.c   |   16 +++++++++
 drivers/isdn/mISDN/layer2.c |   75 ++++++++++++++++++++++++------------------
 include/linux/mISDNif.h     |    3 +-
 3 files changed, 61 insertions(+), 33 deletions(-)

diff --git a/drivers/isdn/mISDN/core.c b/drivers/isdn/mISDN/core.c
index a24530f..c401634 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/layer2.c b/drivers/isdn/mISDN/layer2.c
index d421495..2829d93 100644
--- a/drivers/isdn/mISDN/layer2.c
+++ b/drivers/isdn/mISDN/layer2.c
@@ -110,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);
 }
@@ -154,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);
 	}
 }
@@ -178,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);
 	}
 }
@@ -189,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;
 }
 
@@ -289,18 +292,18 @@ l2_timeout(struct FsmInst *fi, int event, void *arg)
 
 	skb = mI_alloc_skb(0, GFP_ATOMIC);
 	if (!skb) {
-		printk(KERN_WARNING "L2(%d,%d) nr:%x timer %s lost - no skb\n",
-			l2->sapi, l2->tei, l2->ch.nr, event == EV_L2_T200 ?
-			"T200" : "T203");
+		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 "L2(%d,%d) nr:%x timer %s expired\n",
-			l2->sapi, l2->tei, l2->ch.nr, event == EV_L2_T200 ?
-			"T200" : "T203");
+		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);
 }
@@ -309,8 +312,8 @@ 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) {
@@ -632,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;
 		}
 	}
@@ -1118,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);
@@ -1179,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);
@@ -1490,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;
@@ -1511,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);
@@ -1892,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;
@@ -1901,7 +1907,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: sapi %d/%d mismatch\n",
-				       __func__, psapi, l2->sapi);
+				    mISDNDevName4ch(&l2->ch), psapi, l2->sapi);
 			dev_kfree_skb(skb);
 			return 0;
 		}
@@ -1909,7 +1915,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;
 		}
@@ -1950,7 +1956,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;
@@ -1964,15 +1971,16 @@ 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",
-				__func__, hh->prim, hh->id);
+				mISDNDevName4ch(&l2->ch), hh->prim, hh->id);
 	}
 	switch (hh->prim) {
 	case PH_DATA_IND:
@@ -2053,7 +2061,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);
@@ -2066,7 +2075,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;
 	}
@@ -2098,7 +2108,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/include/linux/mISDNif.h b/include/linux/mISDNif.h
index 322d316..f474f40 100644
--- a/include/linux/mISDNif.h
+++ b/include/linux/mISDNif.h
@@ -37,7 +37,7 @@
  */
 #define	MISDN_MAJOR_VERSION	1
 #define	MISDN_MINOR_VERSION	1
-#define MISDN_RELEASE		27
+#define MISDN_RELEASE		28
 
 /* primitives for information exchange
  * generell format
@@ -598,6 +598,7 @@ static inline struct mISDNdevice *dev_to_mISDN(struct device *dev)
 extern void	set_channel_address(struct mISDNchannel *, u_int, u_int);
 extern void	mISDN_clock_update(struct mISDNclock *, int, struct timeval *);
 extern unsigned short mISDN_clock_get(void);
+extern const char *mISDNDevName4ch(struct mISDNchannel *);
 
 #endif /* __KERNEL__ */
 #endif /* mISDNIF_H */
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 8/8] mISDN: Add 2MBit mode for HFC E1 card
  2012-04-28 11:43 [PATCH 0/8] mISDN: Collection of patches for layer1/layer2 Karsten Keil
                   ` (6 preceding siblings ...)
  2012-04-28 11:43 ` [PATCH 7/8] mISDN: Help to identify the card Karsten Keil
@ 2012-04-28 11:43 ` Karsten Keil
  7 siblings, 0 replies; 14+ messages in thread
From: Karsten Keil @ 2012-04-28 11:43 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Karsten Keil

From: Karsten Keil <isdn@linux-pingi.de>

The new mode allows to receive and transmit full transparent
or HDLC data of all timeslots via one FIFO.
Change some register names to match the latest manual for
the E1 chip.

Signed-off-by: Karsten Keil <kkeil@linux-pingi.de>
---
 drivers/isdn/hardware/mISDN/hfc_multi.h |   79 +++---
 drivers/isdn/hardware/mISDN/hfcmulti.c  |  426 ++++++++++++++++++++++++++-----
 include/linux/mISDNif.h                 |   57 +++--
 3 files changed, 440 insertions(+), 122 deletions(-)

diff --git a/drivers/isdn/hardware/mISDN/hfc_multi.h b/drivers/isdn/hardware/mISDN/hfc_multi.h
index c601f88..9dc0543 100644
--- a/drivers/isdn/hardware/mISDN/hfc_multi.h
+++ b/drivers/isdn/hardware/mISDN/hfc_multi.h
@@ -12,6 +12,7 @@
 #define	DEBUG_HFCMULTI_FILL	0x00800000
 #define	DEBUG_HFCMULTI_SYNC	0x01000000
 #define	DEBUG_HFCMULTI_DTMF	0x02000000
+#define	DEBUG_HFCMULTI_TIMER	0x04000000
 #define	DEBUG_HFCMULTI_LOCK	0x80000000
 
 #define	PCI_ENA_REGIO	0x01
@@ -71,7 +72,10 @@ struct hfcm_hw {
 	u_char	r_dtmf;
 	u_char	r_st_sync;
 	u_char	r_sci_msk;
-	u_char	r_tx0, r_tx1;
+	u_char	r_tx0;
+	u_char	r_tx1;
+	u_char	r_rx_sl0_cfg0;
+	u_char	r_tx_sl0_cfg1;
 	u_char	a_st_ctrl0[8];
 	u_char	r_bert_wd_md;
 	timer_t	timer;
@@ -114,6 +118,7 @@ struct hfcm_hw {
 /* hw */
 #define	HFC_CHIP_PLXSD		14 /* whether we have a Speech-Design PLX */
 #define	HFC_CHIP_EMBSD          15 /* whether we have a SD Embedded board */
+#define HFC_CHIP_2MBITRAW	16 /* mode to access full 32 byte data */
 
 #define HFC_IO_MODE_PCIMEM	0x00 /* normal memory mapped IO */
 #define HFC_IO_MODE_REGIO	0x01 /* PCI io access */
@@ -334,24 +339,23 @@ struct hfc_multi {
 #define R_LOS0			0x22
 #define R_LOS1			0x23
 #define R_RX0			0x24
-#define R_RX_FR0		0x25
-#define R_RX_FR1		0x26
+#define R_RX_SL0_CFG0		0x25
+#define R_RX_SL0_CFG1		0x26
 #define R_TX0			0x28
 #define R_TX1			0x29
-#define R_TX_FR0		0x2C
-
-#define R_TX_FR1		0x2D
-#define R_TX_FR2		0x2E
-#define R_JATT_ATT		0x2F /* undocumented */
+#define R_TX_SL0_CFG0		0x2C
+#define R_TX_SL0		0x2D
+#define R_TX_SL0_CFG1		0x2E
+#define R_JATT_CFG		0x2F
 #define A_ST_RD_STATE		0x30
 #define A_ST_WR_STATE		0x30
-#define R_RX_OFF		0x30
+#define R_RX_OFFS		0x30
 #define A_ST_CTRL0		0x31
 #define R_SYNC_OUT		0x31
 #define A_ST_CTRL1		0x32
 #define A_ST_CTRL2		0x33
 #define A_ST_SQ_WR		0x34
-#define R_TX_OFF		0x34
+#define R_TX_OFFS		0x34
 #define R_SYNC_CTRL		0x35
 #define A_ST_CLK_DLY		0x37
 #define R_PWM0			0x38
@@ -414,8 +418,8 @@ struct hfc_multi {
 #define R_RX_SL0_0		0x25
 #define R_RX_SL0_1		0x26
 #define R_RX_SL0_2		0x27
-#define R_JATT_DIR		0x2b /* undocumented */
-#define R_SLIP			0x2c
+#define R_JATT_STA		0x2B
+#define R_SLIP			0x2C
 #define A_ST_RD_STA		0x30
 #define R_FAS_EC		0x30
 #define R_FAS_ECL		0x30
@@ -430,12 +434,12 @@ struct hfc_multi {
 #define R_E_EC			0x36
 #define R_E_ECL			0x36
 #define R_E_ECH			0x37
-#define R_SA6_SA13_EC		0x38
-#define R_SA6_SA13_ECL		0x38
-#define R_SA6_SA13_ECH		0x39
-#define R_SA6_SA23_EC		0x3A
-#define R_SA6_SA23_ECL		0x3A
-#define R_SA6_SA23_ECH		0x3B
+#define R_SA6_VAL13_EC		0x38
+#define R_SA6_VAL13_ECL		0x38
+#define R_SA6_VAL13_ECH		0x39
+#define R_SA6_VAL23_EC		0x3A
+#define R_SA6_VAL23_ECL		0x3A
+#define R_SA6_VAL23_ECH		0x3B
 #define A_ST_B1_RX		0x3C
 #define A_ST_B2_RX		0x3D
 #define A_ST_D_RX		0x3E
@@ -624,7 +628,7 @@ struct hfc_multi {
 #define V_RX_INV_CLK		0x20
 #define V_RX_INV_DATA		0x40
 #define V_AIS_ITU		0x80
-/* R_RX_FR0 */
+/* R_RX_SL0_CFG0 */
 #define V_NO_INSYNC		0x01
 #define V_AUTO_RESYNC		0x02
 #define V_AUTO_RECO		0x04
@@ -633,7 +637,7 @@ struct hfc_multi {
 #define V_XCRC_SYNC		0x20
 #define V_MF_RESYNC		0x40
 #define V_RESYNC		0x80
-/* R_RX_FR1 */
+/* R_RX_SL0_CFG1 */
 #define V_RX_MF			0x01
 #define V_RX_MF_SYNC		0x02
 #define V_RX_SL0_RAM		0x04
@@ -654,17 +658,17 @@ struct hfc_multi {
 #define V_ATX			0x20
 #define V_NTRI			0x40
 #define V_AUTO_ERR_RES		0x80
-/* R_TX_FR0 */
+/* R_TX_SL0_CFG0 */
 #define V_TRP_FAS		0x01
 #define V_TRP_NFAS		0x02
 #define V_TRP_RAL		0x04
 #define V_TRP_SA		0x08
-/* R_TX_FR1 */
+/* R_TX_SL0 */
 #define V_TX_FAS		0x01
 #define V_TX_NFAS		0x02
 #define V_TX_RAL		0x04
 #define V_TX_SA			0x08
-/* R_TX_FR2 */
+/* R_TX_SL0_CFG1 */
 #define V_TX_MF			0x01
 #define V_TRP_SL0		0x02
 #define V_TX_SL0_RAM		0x04
@@ -672,7 +676,7 @@ struct hfc_multi {
 #define V_NEG_E			0x20
 #define V_XS12_ON		0x40
 #define V_XS15_ON		0x80
-/* R_RX_OFF */
+/* R_RX_OFFS */
 #define V_RX_SZ			0x01
 #define V_RX_INIT		0x04
 /* R_SYNC_OUT */
@@ -680,7 +684,7 @@ struct hfc_multi {
 #define V_IPATS0		0x20
 #define V_IPATS1		0x40
 #define V_IPATS2		0x80
-/* R_TX_OFF */
+/* R_TX_OFFS */
 #define V_TX_SZ			0x01
 #define V_TX_INIT		0x04
 /* R_SYNC_CTRL */
@@ -1119,20 +1123,20 @@ struct hfc_register_names {
 	{"R_LOS0",		0x22},
 	{"R_LOS1",		0x23},
 	{"R_RX0",		0x24},
-	{"R_RX_FR0",		0x25},
-	{"R_RX_FR1",		0x26},
+	{"R_RX_SL0_CFG0",	0x25},
+	{"R_RX_SL0_CFG1",	0x26},
 	{"R_TX0",		0x28},
 	{"R_TX1",		0x29},
-	{"R_TX_FR0",		0x2C},
-	{"R_TX_FR1",		0x2D},
-	{"R_TX_FR2",		0x2E},
+	{"R_TX_SL0_CFG0",	0x2C},
+	{"R_TX_SL0",		0x2D},
+	{"R_TX_SL0_CFG1",	0x2E},
 	{"R_JATT_ATT",		0x2F},
-	{"A_ST_xx_STA/R_RX_OFF", 0x30},
+	{"A_ST_xx_STA/R_RX_OFFS", 0x30},
 	{"A_ST_CTRL0/R_SYNC_OUT", 0x31},
 	{"A_ST_CTRL1",		0x32},
 	{"A_ST_CTRL2",		0x33},
 	{"A_ST_SQ_WR",		0x34},
-	{"R_TX_OFF",		0x34},
+	{"R_TX_OFFS",		0x34},
 	{"R_SYNC_CTRL",		0x35},
 	{"A_ST_CLK_DLY",	0x37},
 	{"R_PWM0",		0x38},
@@ -1194,8 +1198,9 @@ struct hfc_register_names {
 	{"R_RX_SL0_0",		0x25},
 	{"R_RX_SL0_1",		0x26},
 	{"R_RX_SL0_2",		0x27},
-	{"R_JATT_DIR",		0x2b},
+	{"R_JATT_STA",		0x2b},
 	{"R_SLIP",		0x2c},
+	{"R_JATT_CFG",		0x2f},
 	{"A_ST_RD_STA",		0x30},
 	{"R_FAS_ECL",		0x30},
 	{"R_FAS_ECH",		0x31},
@@ -1205,10 +1210,10 @@ struct hfc_register_names {
 	{"R_CRC_ECH",		0x35},
 	{"R_E_ECL",		0x36},
 	{"R_E_ECH",		0x37},
-	{"R_SA6_SA13_ECL",	0x38},
-	{"R_SA6_SA13_ECH",	0x39},
-	{"R_SA6_SA23_ECL",	0x3A},
-	{"R_SA6_SA23_ECH",	0x3B},
+	{"R_SA6_VAL13_ECL",	0x38},
+	{"R_SA6_VAL13_ECH",	0x39},
+	{"R_SA6_VAL23_ECL",	0x3A},
+	{"R_SA6_VAL23_ECH",	0x3B},
 	{"A_ST_B1_RX",		0x3C},
 	{"A_ST_B2_RX",		0x3D},
 	{"A_ST_D_RX",		0x3E},
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index 4301331..06be60c 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -64,7 +64,7 @@
  *
  *	HFC-E1 only bits:
  *	Bit 0     = 0x0001 = interface: 0=copper, 1=optical
- *	Bit 1     = 0x0002 = reserved (later for 32 B-channels transparent mode)
+ *	Bit 1     = 0x0002 = 32 B-channels bundle mode (one channel)
  *	Bit 2     = 0x0004 = Report LOS
  *	Bit 3     = 0x0008 = Report AIS
  *	Bit 4     = 0x0010 = Report SLIP
@@ -1269,11 +1269,10 @@ init_chip(struct hfc_multi *hc)
 		if (debug & DEBUG_HFCMULTI_INIT)
 			printk(KERN_DEBUG "%s: setting PCM into slave mode\n",
 			       __func__);
-	} else
-		if (test_bit(HFC_CHIP_PCM_MASTER, &hc->chip) && !plxsd_master) {
+	} else  if (test_bit(HFC_CHIP_PCM_MASTER, &hc->chip) && !plxsd_master) {
 			if (debug & DEBUG_HFCMULTI_INIT)
 				printk(KERN_DEBUG "%s: setting PCM into master mode\n",
-				       __func__);
+				__func__);
 			hc->hw.r_pcm_md0 |= V_PCM_MD;
 		} else {
 			if (debug & DEBUG_HFCMULTI_INIT)
@@ -1288,7 +1287,18 @@ init_chip(struct hfc_multi *hc)
 			 0x11 /* 16 Bytes TX/RX */);
 	else
 		HFC_outb(hc, R_RAM_SZ, hc->hw.r_ram_sz);
-	HFC_outb(hc, R_FIFO_MD, 0);
+	if (test_bit(HFC_CHIP_2MBITRAW, &hc->chip) &&
+	    (hc->ctype == HFC_TYPE_E1)) {
+		if (debug & DEBUG_HFCMULTI_INIT)
+			printk(KERN_DEBUG "%s: setting 2MBit raw mode\n",
+				__func__);
+		HFC_outb(hc, R_FIFO_MD, 0x0c);
+		hc->Flen = 0x10;
+		hc->Zmin = 0x80;
+		hc->Zlen = 384;
+
+	} else
+		HFC_outb(hc, R_FIFO_MD, 0);
 	if (hc->ctype == HFC_TYPE_XHFC)
 		hc->hw.r_cirm = V_SRES | V_HFCRES | V_PCMRES | V_STRES;
 	else
@@ -1334,7 +1344,8 @@ init_chip(struct hfc_multi *hc)
 	if (hc->slots == 128)
 		HFC_outb(hc, R_PCM_MD1, 0x20);
 	HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0xa0);
-	if (test_bit(HFC_CHIP_PLXSD, &hc->chip))
+	if (test_bit(HFC_CHIP_PLXSD, &hc->chip) ||
+		test_bit(HFC_CHIP_PCM_MASTER, &hc->chip))
 		HFC_outb(hc, R_PCM_MD2, V_SYNC_SRC); /* sync via SYNC_I / O */
 	else if (test_bit(HFC_CHIP_EMBSD, &hc->chip))
 		HFC_outb(hc, R_PCM_MD2, 0x10); /* V_C2O_EN */
@@ -1956,7 +1967,10 @@ hfcmulti_tx(struct hfc_multi *hc, int ch)
 	int *idxp;
 
 	bch = hc->chan[ch].bch;
-	dch = hc->chan[ch].dch;
+	if (!bch)
+		dch = hc->chan[ch].dch;
+	else
+		dch = NULL;
 	if ((!dch) && (!bch))
 		return;
 
@@ -2205,7 +2219,11 @@ hfcmulti_rx(struct hfc_multi *hc, int ch)
 	int	maxlen;
 
 	bch = hc->chan[ch].bch;
-	dch = hc->chan[ch].dch;
+	if (!bch)
+		dch = hc->chan[ch].dch;
+	else
+		dch = NULL;
+
 	if ((!dch) && (!bch))
 		return;
 	if (dch) {
@@ -2264,20 +2282,20 @@ 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__);
-			return;
-		}
-	}
 	/* show activity */
 	if (dch)
 		hc->activity_rx |= 1 << hc->chan[ch].port;
 
 	/* empty fifo with what we have */
 	if (dch || test_bit(FLG_HDLC, &bch->Flags)) {
+		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__);
+				return;
+			}
+		}
 		if (debug & DEBUG_HFCMULTI_FIFO)
 			printk(KERN_DEBUG "%s(card %d): fifo(%d) reading %d "
 			       "bytes (z1=%04x, z2=%04x) HDLC %s (f1=%d, f2=%d) "
@@ -2355,24 +2373,18 @@ next_frame:
 		/* there is an incomplete frame */
 	} else {
 		/* transparent */
+		if (*sp == NULL) {
+			*sp = mI_alloc_skb(Zsize, GFP_ATOMIC);
+			if (*sp == NULL) {
+				printk(KERN_DEBUG "%s: No mem for rx_skb\n",
+				    __func__);
+				return;
+			}
+		}
 		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;
-		}
+		skb = NULL;
 		if (debug & DEBUG_HFCMULTI_FIFO)
 			printk(KERN_DEBUG
 			       "%s(card %d): fifo(%d) reading %d bytes "
@@ -2409,7 +2421,7 @@ signal_state_up(struct dchannel *dch, int info, char *msg)
 static inline void
 handle_timer_irq(struct hfc_multi *hc)
 {
-	int		ch, temp;
+	int		ch, temp, ch_activ = 0;
 	struct dchannel	*dch;
 	u_long		flags;
 
@@ -2443,10 +2455,33 @@ handle_timer_irq(struct hfc_multi *hc)
 		hc->e1_resync = 0;
 		spin_unlock_irqrestore(&HFClock, flags);
 	}
-
-	if (hc->ctype != HFC_TYPE_E1 || hc->e1_state == 1)
+	if (test_bit(HFC_CHIP_2MBITRAW, &hc->chip)) {
+		ch = 0;
+		if (hc->created[hc->chan[ch].port] && hc->chan[ch].bch &&
+		    test_bit(FLG_ACTIVE, &hc->chan[ch].bch->Flags)) {
+			ch_activ++;
+			hfcmulti_tx(hc, ch);
+			hfcmulti_rx(hc, ch);
+			if (hc->chan[ch].dch &&
+			    hc->chan[ch].nt_timer > -1) {
+				dch = hc->chan[ch].dch;
+				if (!(--hc->chan[ch].nt_timer)) {
+					schedule_event(dch,
+					    FLG_PHCHANGE);
+					if (debug &
+					    DEBUG_HFCMULTI_STATE)
+						printk(KERN_DEBUG
+						    "%s: nt_timer at "
+						    "state %x\n",
+						    __func__,
+						    dch->state);
+				}
+			}
+		}
+	} else if (hc->ctype != HFC_TYPE_E1 || hc->e1_state == 1) {
 		for (ch = 0; ch <= 31; ch++) {
 			if (hc->created[hc->chan[ch].port]) {
+				ch_activ++;
 				hfcmulti_tx(hc, ch);
 				/* fifo is started when switching to rx-fifo */
 				hfcmulti_rx(hc, ch);
@@ -2467,6 +2502,11 @@ handle_timer_irq(struct hfc_multi *hc)
 				}
 			}
 		}
+	}
+	if (debug & DEBUG_HFCMULTI_TIMER)
+		printk(KERN_DEBUG "Timer IRQ id%dp%d st%d activ %d\n",
+			hc->id, hc->ports, hc->e1_state, ch_activ);
+
 	if (hc->ctype == HFC_TYPE_E1 && hc->created[0]) {
 		dch = hc->chan[hc->dnum[0]].dch;
 		/* LOS */
@@ -2515,7 +2555,7 @@ handle_timer_irq(struct hfc_multi *hc)
 						"RDI gone");
 			hc->chan[hc->dnum[0]].rdi = temp;
 		}
-		temp = HFC_inb_nodebug(hc, R_JATT_DIR);
+		temp = HFC_inb_nodebug(hc, R_JATT_STA);
 		switch (hc->chan[hc->dnum[0]].sync) {
 		case 0:
 			if ((temp & 0x60) == 0x60) {
@@ -2524,9 +2564,9 @@ handle_timer_irq(struct hfc_multi *hc)
 					       "%s: (id=%d) E1 now "
 					       "in clock sync\n",
 					       __func__, hc->id);
-				HFC_outb(hc, R_RX_OFF,
+				HFC_outb(hc, R_RX_OFFS,
 				    hc->chan[hc->dnum[0]].jitter | V_RX_INIT);
-				HFC_outb(hc, R_TX_OFF,
+				HFC_outb(hc, R_TX_OFFS,
 				    hc->chan[hc->dnum[0]].jitter | V_RX_INIT);
 				hc->chan[hc->dnum[0]].sync = 1;
 				goto check_framesync;
@@ -2660,6 +2700,8 @@ fifo_irq(struct hfc_multi *hc, int block)
 
 	r_irq_fifo_bl = HFC_inb_nodebug(hc, R_IRQ_FIFO_BL0 + block);
 	j = 0;
+	printk(KERN_DEBUG "%s: block %d fifo_bl %02x\n", __func__,
+		block, r_irq_fifo_bl);
 	while (j < 8) {
 		ch = (block << 2) + (j >> 1);
 		dch = hc->chan[ch].dch;
@@ -2870,6 +2912,52 @@ hfcmulti_dbusy_timer(struct hfc_multi *hc)
 {
 }
 
+/* special mode to transmit/revceive full frame (all timeslots) in fifo 0 */
+
+static int set_2MBit_mode(struct hfc_multi *hc, int prot)
+{
+	u8 ch, lim;
+
+	for (ch = 0; ch < 64; ch++) {
+		/* Reset all fifo */
+		HFC_outb(hc, R_FIFO, ch);
+		HFC_wait(hc);
+		HFC_outb(hc, R_INC_RES_FIFO, 6);
+	}
+
+	HFC_outb(hc, R_FIRST_FIFO, 0x0);
+	lim = 63;
+	for (ch = 0; ch < 64; ch++) {
+		HFC_outb(hc, R_FSM_IDX, ch);
+		HFC_wait(hc);
+		HFC_outb(hc, A_CHANNEL, ch);
+		HFC_outb(hc, A_FIFO_SEQ, (ch + 1) % 2);
+		if (prot == ISDN_P_B_HDLC)
+			HFC_outb(hc, A_CON_HDLC, 0x4);
+		else
+			HFC_outb(hc, A_CON_HDLC, 0x6);
+		HFC_outb(hc, A_SUBCH_CFG, 0);
+		if (ch == lim)
+			break;
+	}
+	HFC_outb(hc, A_FIFO_SEQ, 0x40);
+
+	for (ch = 0; ch < 64; ch++) {
+		u8 ach, asc, ac, afs, ais, af1, af2;
+		HFC_outb(hc, R_FIFO, ch);
+		HFC_wait(hc);
+		ach = HFC_inb(hc, A_CON_HDLC);
+		asc = HFC_inb(hc, A_SUBCH_CFG);
+		ac = HFC_inb(hc,  A_CHANNEL);
+		afs = HFC_inb(hc, A_FIFO_SEQ);
+		ais = HFC_inb(hc, A_IRQ_MSK);
+		af1 = HFC_inb(hc, A_F1);
+		af2 = HFC_inb(hc, A_F2);
+		printk(KERN_DEBUG "R_FIFO %02d: %02x/%02x/%02x/%02x/%02x %d/%d\n",
+			ch, ach, asc, ac, afs, ais, af1, af2);
+	}
+	return 0;
+}
 
 /*
  * activate/deactivate hardware for selected channels and mode
@@ -3514,12 +3602,24 @@ handle_bmsg(struct mISDNchannel *ch, struct sk_buff *skb)
 		/* activate B-channel if not already activated */
 		if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags)) {
 			hc->chan[bch->slot].txpending = 0;
-			ret = mode_hfcmulti(hc, bch->slot,
-					    ch->protocol,
-					    hc->chan[bch->slot].slot_tx,
-					    hc->chan[bch->slot].bank_tx,
-					    hc->chan[bch->slot].slot_rx,
-					    hc->chan[bch->slot].bank_rx);
+			if (test_bit(HFC_CHIP_2MBITRAW, &hc->chip)) {
+				ret = set_2MBit_mode(hc, ch->protocol);
+				/* The default content for these registers can
+				 * be changed via a MISDN_CTRL_L1_TS0_MODE ctrl
+				 * request
+				 */
+				HFC_outb(hc, R_RX_SL0_CFG0,
+					hc->hw.r_rx_sl0_cfg0);
+				HFC_outb(hc, R_TX_SL0_CFG1,
+					hc->hw.r_tx_sl0_cfg1);
+			} else {
+				ret = mode_hfcmulti(hc, bch->slot,
+					ch->protocol,
+					hc->chan[bch->slot].slot_tx,
+					hc->chan[bch->slot].bank_tx,
+					hc->chan[bch->slot].slot_rx,
+					hc->chan[bch->slot].bank_rx);
+			}
 			if (!ret) {
 				if (ch->protocol == ISDN_P_B_RAW && !hc->dtmf
 				    && test_bit(HFC_CHIP_DTMF, &hc->chip)) {
@@ -3591,11 +3691,13 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
 	int			slot_rx;
 	int			bank_rx;
 	int			num;
+	u8			v1, v2;
 
 	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;
+		cq->op = MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP |
+			MISDN_CTRL_RX_OFF | MISDN_CTRL_FILL_EMPTY |
+			MISDN_CTRL_L1_TESTS;
 		break;
 	case MISDN_CTRL_RX_OFF: /* turn off / on rx stream */
 		hc->chan[bch->slot].rx_off = !!cq->p1;
@@ -3702,6 +3804,38 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
 		else
 			ret = -EINVAL;
 		break;
+	case MISDN_CTRL_L1_TS0_MODE:
+		if (hc->ctype == HFC_TYPE_E1) {
+			v1 = hc->hw.r_rx_sl0_cfg0;
+			v2 = hc->hw.r_tx_sl0_cfg1;
+			if (cq->p1 > -1) {
+				hc->hw.r_rx_sl0_cfg0 = cq->p1 & 0xff;
+				HFC_outb(hc, R_RX_SL0_CFG0, cq->p1 & 0xff);
+				printk(KERN_DEBUG "RX_SL0_CFG0 = %x\n", cq->p1);
+			} else
+				printk(KERN_DEBUG "RX_SL0_CFG0 not modified\n");
+			if (cq->p2 > -1) {
+				hc->hw.r_tx_sl0_cfg1 = cq->p2 & 0xff;
+				HFC_outb(hc, R_TX_SL0_CFG1, cq->p2 & 0xff);
+				printk(KERN_DEBUG "TX_SL0_CFG1 = %x\n", cq->p2);
+			} else
+				printk(KERN_DEBUG "TX_SL0_CFG1 not modified\n");
+			cq->p1 = v1;
+			cq->p2 = v2;
+		} else {
+			printk(KERN_DEBUG "Not E1\n");
+			ret = -EINVAL;
+		}
+		break;
+	case MISDN_CTRL_L1_GET_SYNC_INFO:
+		cq->p1 = HFC_inb(hc, R_E1_RD_STA);
+		cq->p1 |= (HFC_inb(hc, R_SYNC_STA) << 8);
+		cq->p2 = HFC_inb(hc, R_RX_SL0_0);
+		cq->p2 |= (HFC_inb(hc, R_RX_SL0_1) << 8);
+		cq->p2 |= (HFC_inb(hc, R_RX_SL0_2) << 16);
+		cq->p3 = HFC_inb(hc, R_JATT_STA);
+		cq->p3 |= (HFC_inb(hc, R_SLIP) << 8);
+		break;
 	default:
 		printk(KERN_WARNING "%s: unknown Op %x\n",
 		       __func__, cq->op);
@@ -3776,6 +3910,12 @@ ph_state_change(struct dchannel *dch)
 		}
 		switch (dch->state) {
 		case (1):
+			if (test_bit(HFC_CHIP_2MBITRAW, &hc->chip)) {
+				if (debug & DEBUG_HFCMULTI_STATE)
+					printk(KERN_DEBUG
+						"2 MBIT Raw state 1 reached\n");
+				break;
+			}
 			if (hc->e1_state != 1) {
 				for (i = 1; i <= 31; i++) {
 					/* reset fifos on e1 activation */
@@ -3874,6 +4014,113 @@ ph_state_change(struct dchannel *dch)
 	}
 }
 
+int init_2MBit_mode(struct hfc_multi *hc, int nr)
+{
+	u_char		r_e1_wr_sta;
+	int		pt;
+
+	if (debug & DEBUG_HFCMULTI_INIT)
+		printk(KERN_DEBUG "%s: ch%d entered\n", __func__, nr);
+
+	if (nr != 0) {
+		printk(KERN_ERR "Only ch0 supports 2MBit card%d\n", hc->id);
+		return -EINVAL;
+	}
+
+	pt = hc->chan[nr].port;
+	if (pt != 0) {
+		printk(KERN_ERR "Only port 0 in 2MBit mode %d\n", hc->id);
+		return -EINVAL;
+	}
+
+	hc->chan[nr].slot_tx = -1;
+	hc->chan[nr].slot_rx = -1;
+	hc->chan[nr].conf = -1;
+	mode_hfcmulti(hc, nr, ISDN_P_NONE, -1, 0, -1, 0);
+
+	if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[nr].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[nr].cfg)) {
+		HFC_outb(hc, R_RX0, 0);
+		hc->hw.r_tx0 = 0 | V_OUT_EN;
+	} else {
+		HFC_outb(hc, R_RX0, 1);
+		hc->hw.r_tx0 = 1 | V_OUT_EN;
+	}
+	hc->hw.r_tx1 = V_ATX | V_NTRI;
+	HFC_outb(hc, R_TX0, hc->hw.r_tx0);
+	HFC_outb(hc, R_TX1, hc->hw.r_tx1);
+	HFC_outb(hc, R_TX_SL0_CFG0, 0x00);
+	HFC_outb(hc, R_TX_SL0, 0xf8);
+
+	HFC_outb(hc, R_TX_SL0_CFG1, V_TX_MF | V_TX_E | V_NEG_E);
+	/* set transparent SL0 is set on ACTIVATE */
+	hc->hw.r_tx_sl0_cfg1 = V_TX_MF | V_TRP_SL0;
+
+	HFC_outb(hc, R_RX_SL0_CFG0, V_AUTO_RESYNC | V_AUTO_RECO | 0);
+
+	hc->hw.r_rx_sl0_cfg0 = 0x1;
+
+	if (test_bit(HFC_CFG_CRC4, &hc->chan[hc->dnum[0]].cfg))
+		HFC_outb(hc, R_RX_SL0_CFG1, V_RX_MF | V_RX_MF_SYNC);
+
+	/* Default TE mode and clock from interface */
+	r_e1_wr_sta = 1;
+	hc->e1_getclock = 1;
+	if (test_bit(HFC_CHIP_RX_SYNC, &hc->chip))
+		HFC_outb(hc, R_SYNC_OUT, V_SYNC_E1_RX);
+	else
+		HFC_outb(hc, R_SYNC_OUT, 0);
+
+	if (test_bit(HFC_CHIP_E1CLOCK_GET, &hc->chip))
+		hc->e1_getclock = 1;
+	if (test_bit(HFC_CHIP_E1CLOCK_PUT, &hc->chip))
+		hc->e1_getclock = 0;
+	if (test_bit(HFC_CHIP_PCM_SLAVE, &hc->chip)) {
+		/* SLAVE (clock master) */
+		if (debug & DEBUG_HFCMULTI_INIT)
+			printk(KERN_DEBUG
+			    "%s: E1 port is clock master (clock from PCM)\n",
+			    __func__);
+		HFC_outb(hc, R_SYNC_CTRL, V_EXT_CLK_SYNC | V_PCM_SYNC);
+	} else {
+		if (hc->e1_getclock) {
+			/* MASTER (clock slave) */
+			if (debug & DEBUG_HFCMULTI_INIT)
+				printk(KERN_DEBUG
+				       "%s: E1 port is clock slave (clock to PCM)\n",
+				       __func__);
+			HFC_outb(hc, R_SYNC_CTRL, 0);
+		} else {
+			/* MASTER (clock master) */
+			if (debug & DEBUG_HFCMULTI_INIT)
+				printk(KERN_DEBUG
+				       "%s: E1 port is clock master (clock from QUARTZ)\n",
+				       __func__);
+			HFC_outb(hc, R_SYNC_CTRL, V_EXT_CLK_SYNC |
+			    V_PCM_SYNC | V_JATT_OFF);
+			HFC_outb(hc, R_SYNC_OUT, 0);
+		}
+	}
+	HFC_outb(hc, R_JATT_CFG, 0x9c);
+	HFC_outb(hc, R_PWM_MD, V_PWM0_MD);
+	HFC_outb(hc, R_PWM0, 0x50);
+	HFC_outb(hc, R_PWM1, 0xff);
+
+	/* state machine setup */
+	HFC_outb(hc, R_E1_WR_STA, r_e1_wr_sta | V_E1_LD_STA);
+	udelay(10); /* wait at least 5,21us */
+	if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) {
+		hc->syncronized = 0;
+		plxsd_checksync(hc, 0);
+	}
+	if (debug & DEBUG_HFCMULTI_INIT)
+		printk("%s: done\n", __func__);
+	return 0;
+}
+
 /*
  * called for card mode init message
  */
@@ -3928,16 +4175,19 @@ hfcmulti_initmode(struct dchannel *dch)
 		hc->hw.r_tx1 = V_ATX | V_NTRI;
 		HFC_outb(hc, R_TX0, hc->hw.r_tx0);
 		HFC_outb(hc, R_TX1, hc->hw.r_tx1);
-		HFC_outb(hc, R_TX_FR0, 0x00);
-		HFC_outb(hc, R_TX_FR1, 0xf8);
+		HFC_outb(hc, R_TX_SL0_CFG0, 0x00);
+		HFC_outb(hc, R_TX_SL0, 0xf8);
 
-		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);
+		if (test_bit(HFC_CFG_CRC4, &hc->chan[hc->dnum[0]].cfg)) {
+			hc->hw.r_tx_sl0_cfg1 = V_TX_MF | V_TX_E | V_NEG_E;
+			HFC_outb(hc, R_TX_SL0_CFG1, hc->hw.r_tx_sl0_cfg1);
+		}
 
-		HFC_outb(hc, R_RX_FR0, V_AUTO_RESYNC | V_AUTO_RECO | 0);
+		hc->hw.r_rx_sl0_cfg0 = V_AUTO_RESYNC | V_AUTO_RECO;
+		HFC_outb(hc, R_RX_SL0_CFG0, hc->hw.r_rx_sl0_cfg0);
 
 		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);
+			HFC_outb(hc, R_RX_SL0_CFG1, V_RX_MF | V_RX_MF_SYNC);
 
 		if (dch->dev.D.protocol == ISDN_P_NT_E1) {
 			if (debug & DEBUG_HFCMULTI_INIT)
@@ -3987,7 +4237,7 @@ hfcmulti_initmode(struct dchannel *dch)
 				HFC_outb(hc, R_SYNC_OUT, 0);
 			}
 		}
-		HFC_outb(hc, R_JATT_ATT, 0x9c); /* undoc register */
+		HFC_outb(hc, R_JATT_CFG, 0x9c); /* undoc register */
 		HFC_outb(hc, R_PWM_MD, V_PWM0_MD);
 		HFC_outb(hc, R_PWM0, 0x50);
 		HFC_outb(hc, R_PWM1, 0xff);
@@ -4086,6 +4336,9 @@ open_dchannel(struct hfc_multi *hc, struct dchannel *dch,
 	if (debug & DEBUG_HW_OPEN)
 		printk(KERN_DEBUG "%s: dev(%d) open from %p\n", __func__,
 		       dch->dev.id, __builtin_return_address(0));
+	if (test_bit(HFC_CHIP_2MBITRAW, &hc->chip) &&
+	    (hc->ctype == HFC_TYPE_E1)) /* No Dchannel in this mode */
+		return -EINVAL;
 	if (rq->protocol == ISDN_P_NONE)
 		return -EINVAL;
 	if ((dch->dev.D.protocol != ISDN_P_NONE) &&
@@ -4122,15 +4375,20 @@ open_bchannel(struct hfc_multi *hc, struct dchannel *dch,
 	      struct channel_req *rq)
 {
 	struct bchannel	*bch;
-	int		ch;
+	int		ret, ch;
 
 	if (!test_channelmap(rq->adr.channel, dch->dev.channelmap))
 		return -EINVAL;
 	if (rq->protocol == ISDN_P_NONE)
 		return -EINVAL;
-	if (hc->ctype == HFC_TYPE_E1)
+	if (hc->ctype == HFC_TYPE_E1) {
 		ch = rq->adr.channel;
-	else
+		if (test_bit(HFC_CHIP_2MBITRAW, &hc->chip)) {
+			ret = init_2MBit_mode(hc, ch);
+			if (ret)
+				return ret;
+		}
+	} else
 		ch = (rq->adr.channel - 1) + (dch->slot - 2);
 	bch = hc->chan[ch].bch;
 	if (!bch) {
@@ -4141,6 +4399,7 @@ 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;
@@ -4158,10 +4417,11 @@ channel_dctrl(struct dchannel *dch, struct mISDN_ctrl_req *cq)
 	struct hfc_multi	*hc = dch->hw;
 	int	ret = 0;
 	int	wd_mode, wd_cnt;
+	u_char	reg, reg1;
 
 	switch (cq->op) {
 	case MISDN_CTRL_GETOP:
-		cq->op = MISDN_CTRL_HFC_OP;
+		cq->op = MISDN_CTRL_HFC_OP | MISDN_CTRL_L1_TESTS;
 		break;
 	case MISDN_CTRL_HFC_WD_INIT: /* init the watchdog */
 		wd_cnt = cq->p1 & 0xf;
@@ -4191,6 +4451,42 @@ 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_STATE_TEST:
+		if (hc->ctype == HFC_TYPE_E1) {
+			/* undocumented: status changes during read */
+			reg = HFC_inb_nodebug(hc, R_E1_RD_STA);
+			while (reg != (reg1 =
+				HFC_inb_nodebug(hc, R_E1_RD_STA))) {
+				if (debug & DEBUG_HFCMULTI_STATE)
+					printk(KERN_DEBUG
+					       "%s: reread STATE because %d!=%d\n",
+					       __func__, reg, reg1);
+				reg = reg1; /* repeat */
+			}
+			printk(KERN_DEBUG "Old L1 state %02x\n", reg);
+			reg &= 0x07;
+			if (cq->p1 < 0 || cq->p1 > 6) /* reset auto mode */
+				HFC_outb(hc, R_E1_WR_STA, reg);
+			else {/* force new state state */
+				reg = cq->p1 & 0x07;
+				HFC_outb(hc, R_E1_WR_STA, reg | V_E1_LD_STA);
+				printk(KERN_DEBUG "New L1 state %02x\n", reg);
+			}
+		} else
+			ret = -EINVAL;
+		break;
+	case MISDN_CTRL_L1_AIS_TEST:
+		if (hc->ctype == HFC_TYPE_E1) {
+			printk(KERN_DEBUG "Old AIS state %02x\n", hc->hw.r_tx1);
+			if (cq->p1)
+				hc->hw.r_tx1 |= V_AIS_OUT;
+			else
+				hc->hw.r_tx1 &= ~V_AIS_OUT;
+			HFC_outb(hc, R_TX1, hc->hw.r_tx1);
+			printk(KERN_DEBUG "New AIS state %02x\n", hc->hw.r_tx1);
+		} else
+			ret = -EINVAL;
+		break;
 	default:
 		printk(KERN_WARNING "%s: unknown Op %x\n",
 		       __func__, cq->op);
@@ -4843,7 +5139,18 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m, int pt)
 	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);
+	if (port[Port_cnt] & 0x0002) {
+		if (debug & DEBUG_HFCMULTI_INIT)
+			printk(KERN_DEBUG
+			       "%s: PORT 2MBit raw mode E1: card(%d) port(%d)\n",
+			       __func__, HFC_cnt + 1, 1);
+		test_and_set_bit(HFC_CHIP_2MBITRAW, &hc->chip);
+		dch->dev.Dprotocols = (1 << ISDN_P_NONE);
+		hc->dnum[pt] = 0;
+		hc->bmask[pt] = 1;
+	} else
+		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;
@@ -4852,8 +5159,9 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m, int 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 */
+	for (ch = 0; ch <= 31; ch++) {
+		/* skip unused channel */
+		if (!((1 << ch) & hc->bmask[pt]))
 			continue;
 		bch = kzalloc(sizeof(struct bchannel), GFP_KERNEL);
 		if (!bch) {
diff --git a/include/linux/mISDNif.h b/include/linux/mISDNif.h
index f474f40..850fe1f 100644
--- a/include/linux/mISDNif.h
+++ b/include/linux/mISDNif.h
@@ -37,7 +37,7 @@
  */
 #define	MISDN_MAJOR_VERSION	1
 #define	MISDN_MINOR_VERSION	1
-#define MISDN_RELEASE		28
+#define MISDN_RELEASE		29
 
 /* primitives for information exchange
  * generell format
@@ -363,31 +363,36 @@ clear_channelmap(u_int nr, u_char *map)
 }
 
 /* CONTROL_CHANNEL parameters */
-#define MISDN_CTRL_GETOP		0x0000
-#define MISDN_CTRL_LOOP			0x0001
-#define MISDN_CTRL_CONNECT		0x0002
-#define MISDN_CTRL_DISCONNECT		0x0004
-#define MISDN_CTRL_GET_PCM_SLOTS	0x0010
-#define MISDN_CTRL_SET_PCM_SLOTS	0x0020
-#define MISDN_CTRL_SETPEER		0x0040
-#define MISDN_CTRL_UNSETPEER		0x0080
-#define MISDN_CTRL_RX_OFF		0x0100
-#define MISDN_CTRL_FILL_EMPTY		0x0200
-#define MISDN_CTRL_GETPEER		0x0400
-#define MISDN_CTRL_L1_TIMER3		0x0800
-#define MISDN_CTRL_HW_FEATURES_OP	0x2000
-#define MISDN_CTRL_HW_FEATURES		0x2001
-#define MISDN_CTRL_HFC_OP		0x4000
-#define MISDN_CTRL_HFC_PCM_CONN		0x4001
-#define MISDN_CTRL_HFC_PCM_DISC		0x4002
-#define MISDN_CTRL_HFC_CONF_JOIN	0x4003
-#define MISDN_CTRL_HFC_CONF_SPLIT	0x4004
-#define MISDN_CTRL_HFC_RECEIVE_OFF	0x4005
-#define MISDN_CTRL_HFC_RECEIVE_ON	0x4006
-#define MISDN_CTRL_HFC_ECHOCAN_ON 	0x4007
-#define MISDN_CTRL_HFC_ECHOCAN_OFF 	0x4008
-#define MISDN_CTRL_HFC_WD_INIT		0x4009
-#define MISDN_CTRL_HFC_WD_RESET		0x400A
+#define MISDN_CTRL_GETOP		0x00000000
+#define MISDN_CTRL_LOOP			0x00000001
+#define MISDN_CTRL_CONNECT		0x00000002
+#define MISDN_CTRL_DISCONNECT		0x00000004
+#define MISDN_CTRL_GET_PCM_SLOTS	0x00000010
+#define MISDN_CTRL_SET_PCM_SLOTS	0x00000020
+#define MISDN_CTRL_SETPEER		0x00000040
+#define MISDN_CTRL_UNSETPEER		0x00000080
+#define MISDN_CTRL_RX_OFF		0x00000100
+#define MISDN_CTRL_FILL_EMPTY		0x00000200
+#define MISDN_CTRL_GETPEER		0x00000400
+#define MISDN_CTRL_L1_TIMER3		0x00000800
+#define MISDN_CTRL_HW_FEATURES_OP	0x00002000
+#define MISDN_CTRL_HW_FEATURES		0x00002001
+#define MISDN_CTRL_HFC_OP		0x00004000
+#define MISDN_CTRL_HFC_PCM_CONN		0x00004001
+#define MISDN_CTRL_HFC_PCM_DISC		0x00004002
+#define MISDN_CTRL_HFC_CONF_JOIN	0x00004003
+#define MISDN_CTRL_HFC_CONF_SPLIT	0x00004004
+#define MISDN_CTRL_HFC_RECEIVE_OFF	0x00004005
+#define MISDN_CTRL_HFC_RECEIVE_ON	0x00004006
+#define MISDN_CTRL_HFC_ECHOCAN_ON	0x00004007
+#define MISDN_CTRL_HFC_ECHOCAN_OFF	0x00004008
+#define MISDN_CTRL_HFC_WD_INIT		0x00004009
+#define MISDN_CTRL_HFC_WD_RESET		0x0000400A
+#define MISDN_CTRL_L1_TESTS		0x00010000
+#define MISDN_CTRL_L1_STATE_TEST	0x00010001
+#define MISDN_CTRL_L1_AIS_TEST		0x00010002
+#define MISDN_CTRL_L1_TS0_MODE		0x00010003
+#define MISDN_CTRL_L1_GET_SYNC_INFO	0x00010004
 
 /* special PCM slot numbers */
 #define MISDN_PCM_SLOT_DISABLE	-1	/* PCM disabled */
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/8] Sometimes the ISDN chip only controls the D-channel
  2012-04-28 11:43 ` [PATCH 3/8] Sometimes the ISDN chip only controls the D-channel Karsten Keil
@ 2012-05-01 17:30   ` David Miller
  2012-05-03  6:31     ` Karsten Keil
  0 siblings, 1 reply; 14+ messages in thread
From: David Miller @ 2012-05-01 17:30 UTC (permalink / raw)
  To: kkeil; +Cc: netdev

From: Karsten Keil <kkeil@linux-pingi.de>
Date: Sat, 28 Apr 2012 13:43:19 +0200

> The B-channels are only accessed via the PCM backplane.
> Add infrastruckture for this special mode.
> 
> Signed-off-by: Karsten Keil <kkeil@linux-pingi.de>

I dread reviewing these ISDN patch sets because they are so
full of problems, and it's so damn obvious how little care is
put into preparing them.

What I see is that you put the minimum amount of work necessary
into splitting up your huge ISDN patch set submission into more
managable pieces, and as a result you are introducing problems.

> diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
> index abe2d69..502bcf1 100644
> --- a/drivers/isdn/mISDN/socket.c
> +++ b/drivers/isdn/mISDN/socket.c
> @@ -270,6 +270,7 @@ data_sock_release(struct socket *sock)
>  		break;
>  	case ISDN_P_LAPD_TE:
>  	case ISDN_P_LAPD_NT:
> +	case ISDN_P_B_PCM:
>  	case ISDN_P_B_RAW:
>  	case ISDN_P_B_HDLC:
>  	case ISDN_P_B_X75SLP:

Ok, that's fine.

> @@ -148,6 +149,8 @@ struct bchannel {
>  	u_int			state;
>  	void			*hw;
>  	int			slot;	/* multiport card channel slot */
> +	int			pcm_tx;	/* PCM tx slot nr */
> +	int			pcm_rx;	/* PCM rx slot nr */
>  	struct timer_list	timer;
>  	/* receive data */
>  	struct sk_buff		*rx_skb;

But what the hell is this?  These structure members are unused by
this patch, and in fact no patch in your entire series uses them.

> @@ -360,8 +360,8 @@ clear_channelmap(u_int nr, u_char *map)
>  #define MISDN_CTRL_LOOP			0x0001
>  #define MISDN_CTRL_CONNECT		0x0002
>  #define MISDN_CTRL_DISCONNECT		0x0004
> -#define MISDN_CTRL_PCMCONNECT		0x0010
> -#define MISDN_CTRL_PCMDISCONNECT	0x0020
> +#define MISDN_CTRL_GET_PCM_SLOTS	0x0010
> +#define MISDN_CTRL_SET_PCM_SLOTS	0x0020
>  #define MISDN_CTRL_SETPEER		0x0040
>  #define MISDN_CTRL_UNSETPEER		0x0080
>  #define MISDN_CTRL_RX_OFF		0x0100

Another completely unrelated change, nothing in this patch uses
these new defines.

> @@ -381,6 +381,10 @@ clear_channelmap(u_int nr, u_char *map)
>  #define MISDN_CTRL_HFC_WD_INIT		0x4009
>  #define MISDN_CTRL_HFC_WD_RESET		0x400A
>  
> +/* special PCM slot numbers */
> +#define MISDN_PCM_SLOT_DISABLE	-1	/* PCM disabled */
> +#define MISDN_PCM_SLOT_IGNORE	-2	/* PCM setting will be not changed */
> +
>  /* socket options */
>  #define MISDN_TIME_STAMP		0x0001
>  

Same thing.

> @@ -389,6 +393,7 @@ struct mISDN_ctrl_req {
>  	int		channel;
>  	int		p1;
>  	int		p2;
> +	int		p3;
>  };
>  
>  /* muxer options */

And again, same problem.

You really need to get your act in gear and prepare your patches
properly, so that they don't have unrelated changes in them.

This is not amateur hour.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/8] Sometimes the ISDN chip only controls the D-channel
  2012-05-01 17:30   ` David Miller
@ 2012-05-03  6:31     ` Karsten Keil
  2012-05-03  6:50       ` David Miller
  0 siblings, 1 reply; 14+ messages in thread
From: Karsten Keil @ 2012-05-03  6:31 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

Hello David,

Am 01.05.2012 19:30, schrieb David Miller:
> From: Karsten Keil <kkeil@linux-pingi.de>
> Date: Sat, 28 Apr 2012 13:43:19 +0200
> 
>> The B-channels are only accessed via the PCM backplane.
>> Add infrastruckture for this special mode.
>>
>> Signed-off-by: Karsten Keil <kkeil@linux-pingi.de>
> 
> I dread reviewing these ISDN patch sets because they are so
> full of problems, and it's so damn obvious how little care is
> put into preparing them.
> 
> What I see is that you put the minimum amount of work necessary
> into splitting up your huge ISDN patch set submission into more
> managable pieces, and as a result you are introducing problems.
> 

I did put the additional PCM infrastructure in this series, because
the approval test was done with it in place.
I did plan the update of the low level drivers in a separate patchset
from the beginning.

What do you prefer, adding the driver part now, as additional patch, or
removing this additional infrastruckture part and submit it in a later
series ?

>> diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
>> index abe2d69..502bcf1 100644
>> --- a/drivers/isdn/mISDN/socket.c
>> +++ b/drivers/isdn/mISDN/socket.c
>> @@ -270,6 +270,7 @@ data_sock_release(struct socket *sock)
>>  		break;
>>  	case ISDN_P_LAPD_TE:
>>  	case ISDN_P_LAPD_NT:
>> +	case ISDN_P_B_PCM:
>>  	case ISDN_P_B_RAW:
>>  	case ISDN_P_B_HDLC:
>>  	case ISDN_P_B_X75SLP:
> 
> Ok, that's fine.
> 
>> @@ -148,6 +149,8 @@ struct bchannel {
>>  	u_int			state;
>>  	void			*hw;
>>  	int			slot;	/* multiport card channel slot */
>> +	int			pcm_tx;	/* PCM tx slot nr */
>> +	int			pcm_rx;	/* PCM rx slot nr */
>>  	struct timer_list	timer;
>>  	/* receive data */
>>  	struct sk_buff		*rx_skb;
> 
> But what the hell is this?  These structure members are unused by
> this patch, and in fact no patch in your entire series uses them.
> 
>> @@ -360,8 +360,8 @@ clear_channelmap(u_int nr, u_char *map)
>>  #define MISDN_CTRL_LOOP			0x0001
>>  #define MISDN_CTRL_CONNECT		0x0002
>>  #define MISDN_CTRL_DISCONNECT		0x0004
>> -#define MISDN_CTRL_PCMCONNECT		0x0010
>> -#define MISDN_CTRL_PCMDISCONNECT	0x0020
>> +#define MISDN_CTRL_GET_PCM_SLOTS	0x0010
>> +#define MISDN_CTRL_SET_PCM_SLOTS	0x0020
>>  #define MISDN_CTRL_SETPEER		0x0040
>>  #define MISDN_CTRL_UNSETPEER		0x0080
>>  #define MISDN_CTRL_RX_OFF		0x0100
> 
> Another completely unrelated change, nothing in this patch uses
> these new defines.
> 
>> @@ -381,6 +381,10 @@ clear_channelmap(u_int nr, u_char *map)
>>  #define MISDN_CTRL_HFC_WD_INIT		0x4009
>>  #define MISDN_CTRL_HFC_WD_RESET		0x400A
>>  
>> +/* special PCM slot numbers */
>> +#define MISDN_PCM_SLOT_DISABLE	-1	/* PCM disabled */
>> +#define MISDN_PCM_SLOT_IGNORE	-2	/* PCM setting will be not changed */
>> +
>>  /* socket options */
>>  #define MISDN_TIME_STAMP		0x0001
>>  
> 
> Same thing.
> 
>> @@ -389,6 +393,7 @@ struct mISDN_ctrl_req {
>>  	int		channel;
>>  	int		p1;
>>  	int		p2;
>> +	int		p3;
>>  };
>>  
>>  /* muxer options */
> 
> And again, same problem.
> 
> You really need to get your act in gear and prepare your patches
> properly, so that they don't have unrelated changes in them.
> 
> This is not amateur hour.
> 
> 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/8] Sometimes the ISDN chip only controls the D-channel
  2012-05-03  6:31     ` Karsten Keil
@ 2012-05-03  6:50       ` David Miller
  2012-05-03  7:31         ` Karsten Keil
  0 siblings, 1 reply; 14+ messages in thread
From: David Miller @ 2012-05-03  6:50 UTC (permalink / raw)
  To: kkeil; +Cc: netdev

From: Karsten Keil <kkeil@linux-pingi.de>
Date: Thu, 03 May 2012 08:31:57 +0200

> I did put the additional PCM infrastructure in this series, because
> the approval test was done with it in place.
> I did plan the update of the low level drivers in a separate patchset
> from the beginning.
> 
> What do you prefer, adding the driver part now, as additional patch, or
> removing this additional infrastruckture part and submit it in a later
> series ?

I feel like I'm talking to a wall.

A patch should do one, and only one thing.  It should not have
changes which are unrelated to that one thing.

What part of this is so hard to understand?

To make matters worse, you didn't even make a mention of those
unrelated changes in your commit message.

So that patch was bogus on at least two counts.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/8] Sometimes the ISDN chip only controls the D-channel
  2012-05-03  6:50       ` David Miller
@ 2012-05-03  7:31         ` Karsten Keil
  2012-05-03  8:08           ` David Miller
  0 siblings, 1 reply; 14+ messages in thread
From: Karsten Keil @ 2012-05-03  7:31 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

Am 03.05.2012 08:50, schrieb David Miller:
> From: Karsten Keil <kkeil@linux-pingi.de>
> Date: Thu, 03 May 2012 08:31:57 +0200
> 
>> I did put the additional PCM infrastructure in this series, because
>> the approval test was done with it in place.
>> I did plan the update of the low level drivers in a separate patchset
>> from the beginning.
>>
>> What do you prefer, adding the driver part now, as additional patch, or
>> removing this additional infrastruckture part and submit it in a later
>> series ?
> 
> I feel like I'm talking to a wall.
> 
> A patch should do one, and only one thing.  It should not have
> changes which are unrelated to that one thing.
> 

Sorry I disagree here, this patch does exactly one thing, it add the
infrastructure in the mISDN core to allow the PCM only B-channel mode.
PCM only mode need a special protocol and a mechanism to set/get/store
the PCM slots of the card, and this is for what the extra stuff is used.


> What part of this is so hard to understand?
> 
> To make matters worse, you didn't even make a mention of those
> unrelated changes in your commit message.
> 

Yes, I was not verbose enough in the commit message and it was my error
to include it in this series, without the use case. Maybe I'm too
deep in the ISDN stuff so I forget that 3 parties do not see how it fit
together.

So would you accept this patch with a changed commit message like this ?

Sometimes the ISDN chip only controls the D-channel

The B-channels are connected only via the PCM backplane.
For this special case we need two things, a protocol which do not enable
the normal IO path and a method to set/get and store the PCM slots to be
used on the backplane.
This patch add the core infrastructure for both. A later patch will
add the methods to the supported low level drivers.

> So that patch was bogus on at least two counts.
> 
> 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/8] Sometimes the ISDN chip only controls the D-channel
  2012-05-03  7:31         ` Karsten Keil
@ 2012-05-03  8:08           ` David Miller
  0 siblings, 0 replies; 14+ messages in thread
From: David Miller @ 2012-05-03  8:08 UTC (permalink / raw)
  To: kkeil; +Cc: netdev

From: Karsten Keil <kkeil@linux-pingi.de>
Date: Thu, 03 May 2012 09:31:04 +0200

> PCM only mode need a special protocol and a mechanism to set/get/store
> the PCM slots of the card, and this is for what the extra stuff is used.

It changed the values of some macros which are actually used by the
code.

Then it adds members to structures, and defines, which are completely
unused.

The latter part is completely bogus.

This is the second time I'm saying this again.  I'm not saying it
a third time, instead I'll just ignore you.

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2012-05-03  8:08 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-28 11:43 [PATCH 0/8] mISDN: Collection of patches for layer1/layer2 Karsten Keil
2012-04-28 11:43 ` [PATCH 1/8] mISDN: Added PH_* state info to tei manager Karsten Keil
2012-04-28 11:43 ` [PATCH 2/8] mISDN: Fix refcounting bug Karsten Keil
2012-04-28 11:43 ` [PATCH 3/8] Sometimes the ISDN chip only controls the D-channel Karsten Keil
2012-05-01 17:30   ` David Miller
2012-05-03  6:31     ` Karsten Keil
2012-05-03  6:50       ` David Miller
2012-05-03  7:31         ` Karsten Keil
2012-05-03  8:08           ` David Miller
2012-04-28 11:43 ` [PATCH 4/8] mISDN: L2 timeouts need to be queued as L2 event Karsten Keil
2012-04-28 11:43 ` [PATCH 5/8] mISDN: Make layer1 timer 3 value configurable Karsten Keil
2012-04-28 11:43 ` [PATCH 6/8] mISDN: Layer1 statemachine fix Karsten Keil
2012-04-28 11:43 ` [PATCH 7/8] mISDN: Help to identify the card Karsten Keil
2012-04-28 11:43 ` [PATCH 8/8] mISDN: Add 2MBit mode for HFC E1 card Karsten Keil

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.