* [PATCH 27/28] mISDN: Add X-Tensions USB ISDN TA XC-525
From: Karsten Keil @ 2012-04-21 16:19 UTC (permalink / raw)
To: David Miller; +Cc: netdev, isdn4linux
>From http://www.ip-phone-forum.de/showthread.php?t=225313
Thanks to Lars Immisch for pointing to this.
Signed-off-by: Karsten Keil <keil@b1-systems.de>
---
drivers/isdn/hardware/mISDN/hfcsusb.h | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.h b/drivers/isdn/hardware/mISDN/hfcsusb.h
index 7d48b86..56e9755 100644
--- a/drivers/isdn/hardware/mISDN/hfcsusb.h
+++ b/drivers/isdn/hardware/mISDN/hfcsusb.h
@@ -341,6 +341,12 @@ static const char *HFC_NT_LAYER1_STATES[HFC_MAX_NT_LAYER1_STATE + 1] = {
/* supported devices */
static struct usb_device_id hfcsusb_idtab[] = {
{
+ USB_DEVICE(0x1ae7, 0x0525),
+ .driver_info = (unsigned long) &((struct hfcsusb_vdata)
+ {LED_SCHEME1, {0x88, -64, -32, -16},
+ "X-Tensions USB ISDN TA XC-525"}),
+ },
+ {
USB_DEVICE(0x0959, 0x2bd0),
.driver_info = (unsigned long) &((struct hfcsusb_vdata)
{LED_OFF, {4, 0, 2, 1},
--
1.7.3.4
^ permalink raw reply related
* [PATCH 21/28] mISDN: Add interface to allow upper layers to modify RX buffer limits
From: Karsten Keil @ 2012-04-21 15:26 UTC (permalink / raw)
To: David Miller; +Cc: netdev, isdn4linux
It seems to be useful to let applications decide the
size of the data chunks they want receive.
Signed-off-by: Karsten Keil <kkeil@linux-pingi.de>
---
drivers/isdn/hardware/mISDN/avmfritz.c | 17 +++++++++++++----
drivers/isdn/hardware/mISDN/mISDNipac.c | 17 +++++++++++++----
include/linux/mISDNif.h | 11 ++++++++++-
3 files changed, 36 insertions(+), 9 deletions(-)
diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c
index 4b1c86e..9cee744 100644
--- a/drivers/isdn/hardware/mISDN/avmfritz.c
+++ b/drivers/isdn/hardware/mISDN/avmfritz.c
@@ -835,15 +835,24 @@ init_card(struct fritzcard *fc)
static int
channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
{
- int ret = 0;
+ int ret = 0, o1, o2;
struct fritzcard *fc = bch->hw;
switch (cq->op) {
case MISDN_CTRL_GETOP:
- cq->op = 0;
+ cq->op = MISDN_CTRL_RX_BUFFER;
+ break;
+ case MISDN_CTRL_RX_BUFFER:
+ /* We return the old values */
+ o1 = bch->minlen;
+ o2 = bch->maxlen;
+ if (cq->p1 != MISDN_CTRL_RX_SIZE_IGNORE)
+ bch->minlen = cq->p1;
+ if (cq->p2 != MISDN_CTRL_RX_SIZE_IGNORE)
+ bch->minlen = cq->p2;
+ cq->p1 = o1;
+ cq->p2 = o2;
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;
diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c
index 1bc75ae..b32f5bb 100644
--- a/drivers/isdn/hardware/mISDN/mISDNipac.c
+++ b/drivers/isdn/hardware/mISDN/mISDNipac.c
@@ -1395,14 +1395,23 @@ hscx_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
static int
channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
{
- int ret = 0;
+ int ret = 0, o1, o2;
switch (cq->op) {
case MISDN_CTRL_GETOP:
- cq->op = 0;
+ cq->op = MISDN_CTRL_RX_BUFFER;
+ break;
+ case MISDN_CTRL_RX_BUFFER:
+ /* We return the old values */
+ o1 = bch->minlen;
+ o2 = bch->maxlen;
+ if (cq->p1 != MISDN_CTRL_RX_SIZE_IGNORE)
+ bch->minlen = cq->p1;
+ if (cq->p2 != MISDN_CTRL_RX_SIZE_IGNORE)
+ bch->minlen = cq->p2;
+ cq->p1 = o1;
+ cq->p2 = o2;
break;
- /* Nothing implemented yet */
- case MISDN_CTRL_FILL_EMPTY:
default:
pr_info("%s: unknown Op %x\n", __func__, cq->op);
ret = -EINVAL;
diff --git a/include/linux/mISDNif.h b/include/linux/mISDNif.h
index 850fe1f..b26de1a 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 29
+#define MISDN_RELEASE 30
/* primitives for information exchange
* generell format
@@ -367,6 +367,7 @@ clear_channelmap(u_int nr, u_char *map)
#define MISDN_CTRL_LOOP 0x00000001
#define MISDN_CTRL_CONNECT 0x00000002
#define MISDN_CTRL_DISCONNECT 0x00000004
+#define MISDN_CTRL_RX_BUFFER 0x00000008
#define MISDN_CTRL_GET_PCM_SLOTS 0x00000010
#define MISDN_CTRL_SET_PCM_SLOTS 0x00000020
#define MISDN_CTRL_SETPEER 0x00000040
@@ -394,6 +395,14 @@ clear_channelmap(u_int nr, u_char *map)
#define MISDN_CTRL_L1_TS0_MODE 0x00010003
#define MISDN_CTRL_L1_GET_SYNC_INFO 0x00010004
+/* special RX buffer values for MISDN_CTRL_RX_BUFFER
+ * req.p1 is minimum buffer size, req.p2 the maximum
+ * MISDN_CTRL_RX_SIZE_ IGNORE value will not change but is still read back
+ */
+#define MISDN_CTRL_RX_SIZE_NOCHECK -1
+#define MISDN_CTRL_RX_SIZE_IGNORE -2
+
+
/* special PCM slot numbers */
#define MISDN_PCM_SLOT_DISABLE -1 /* PCM disabled */
#define MISDN_PCM_SLOT_IGNORE -2 /* PCM setting will be not changed */
--
1.7.3.4
^ permalink raw reply related
* [PATCH 22/28] mISDN: More support for MISDN_CTRL_FILL_EMPTY and MISDN_CTRL_RX_OFF
From: Karsten Keil @ 2012-04-21 15:39 UTC (permalink / raw)
To: David Miller; +Cc: netdev, isdn4linux
Add a common HW flag to support RX_OFF.
Implement MISDN_CTRL_FILL_EMPTY and MISDN_CTRL_RX_OFF for the avmfritz
driver.
Signed-off-by: Karsten Keil <kkeil@linux-pingi.de>
---
drivers/isdn/hardware/mISDN/avmfritz.c | 169 ++++++++++++++++++++++++--------
drivers/isdn/mISDN/hwchannel.c | 1 +
include/linux/mISDNhw.h | 4 +-
include/linux/mISDNif.h | 10 ++-
4 files changed, 139 insertions(+), 45 deletions(-)
diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c
index 9cee744..3781446 100644
--- a/drivers/isdn/hardware/mISDN/avmfritz.c
+++ b/drivers/isdn/hardware/mISDN/avmfritz.c
@@ -141,6 +141,8 @@ struct fritzcard {
struct isac_hw isac;
struct hdlc_hw hdlc[2];
struct bchannel bch[2];
+ int dropcnt[2];
+ u8 fill[2 * HDLC_FIFO_SIZE_V2];
char log[LOG_SIZE + 1];
};
@@ -402,35 +404,45 @@ static void
hdlc_empty_fifo(struct bchannel *bch, int count)
{
u32 *ptr;
- u8 *p;
+ u8 *p, copy;
u32 val, addr;
int cnt;
struct fritzcard *fc = bch->hw;
pr_debug("%s: %s %d\n", fc->name, __func__, count);
- if (!bch->rx_skb) {
- if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {
- if (count >= bch->minlen)
- cnt = count;
- else
- cnt = 2 * bch->minlen;
- } else
- cnt = bch->maxlen;
- bch->rx_skb = mI_alloc_skb(cnt, GFP_ATOMIC);
+ if (test_bit(FLG_RX_OFF, &bch->Flags)) {
+ /* We drop the content, but need to read all bytes from FIFO */
+ copy = 0;
+ if (debug & DEBUG_HW_BFIFO)
+ printk(KERN_DEBUG "Dropped %d bytes - RX off\n", count);
+ val = (bch->nr - 1) & 1;
+ fc->dropcnt[val] += count;
+ } else {
+ copy = 1;
if (!bch->rx_skb) {
- pr_info("%s: B receive out of memory\n",
- fc->name);
+ if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {
+ if (count >= bch->minlen)
+ cnt = count;
+ else
+ cnt = 2 * bch->minlen;
+ } else
+ cnt = bch->maxlen;
+ bch->rx_skb = mI_alloc_skb(cnt, GFP_ATOMIC);
+ if (!bch->rx_skb) {
+ pr_info("%s: B receive out of memory\n",
+ fc->name);
+ return;
+ }
+ } else
+ cnt = skb_tailroom(bch->rx_skb);
+ if (count > cnt) {
+ pr_debug("%s: overrun %d + %d free %d\n", fc->name,
+ bch->rx_skb->len, count, cnt);
return;
}
- } else
- cnt = skb_tailroom(bch->rx_skb);
- if (count > cnt) {
- pr_debug("%s: overrun %d + %d free %d\n", fc->name,
- bch->rx_skb->len, count, cnt);
- return;
+ p = skb_put(bch->rx_skb, count);
+ ptr = (u32 *)p;
}
- p = skb_put(bch->rx_skb, count);
- ptr = (u32 *)p;
if (AVM_FRITZ_PCIV2 == fc->type)
addr = fc->addr + (bch->nr == 2 ?
AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1);
@@ -441,11 +453,13 @@ hdlc_empty_fifo(struct bchannel *bch, int count)
cnt = 0;
while (cnt < count) {
val = le32_to_cpu(inl(addr));
- put_unaligned(val, ptr);
- ptr++;
+ if (copy) {
+ put_unaligned(val, ptr);
+ ptr++;
+ }
cnt += 4;
}
- if (debug & DEBUG_HW_BFIFO) {
+ if (copy && (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);
@@ -457,19 +471,25 @@ hdlc_fill_fifo(struct bchannel *bch)
{
struct fritzcard *fc = bch->hw;
struct hdlc_hw *hdlc;
- int count, fs, cnt = 0;
+ int count, fs, cnt = 0, idx;
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;
+ idx = (bch->nr - 1) & 1;
+ hdlc = &fc->hdlc[idx];
fs = (fc->type == AVM_FRITZ_PCIV2) ?
HDLC_FIFO_SIZE_V2 : HDLC_FIFO_SIZE_V1;
- p = bch->tx_skb->data + bch->tx_idx;
+ if (!bch->tx_skb) {
+ if (!test_bit(FLG_FILLEMPTY, &bch->Flags))
+ return;
+ count = fs;
+ p = fc->fill + (idx * HDLC_FIFO_SIZE_V2);
+ } 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 > fs) {
count = fs;
@@ -477,10 +497,13 @@ hdlc_fill_fifo(struct bchannel *bch)
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;
+ if (bch->tx_skb) {
+ pr_debug("%s: %s %d/%d/%d", fc->name, __func__, count,
+ bch->tx_idx, bch->tx_skb->len);
+ bch->tx_idx += count;
+ } else
+ pr_debug("%s: %s fillempty %d\n", fc->name, __func__, count);
hdlc->ctrl.sr.xml = ((count == fs) ? 0 : count);
if (AVM_FRITZ_PCIV2 == fc->type) {
__write_ctrl_pciv2(fc, hdlc, bch->nr);
@@ -509,11 +532,10 @@ HDLC_irq_xpr(struct bchannel *bch)
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 (bch->tx_skb)
dev_kfree_skb(bch->tx_skb);
- }
- if (get_next_bframe(bch))
+ if (get_next_bframe(bch) ||
+ test_bit(FLG_FILLEMPTY, &bch->Flags))
hdlc_fill_fifo(bch);
}
}
@@ -523,8 +545,9 @@ HDLC_irq(struct bchannel *bch, u32 stat)
{
struct fritzcard *fc = bch->hw;
int len, fs;
- u32 rmlMask;
+ u32 rmlMask, err;
struct hdlc_hw *hdlc;
+ struct sk_buff *skb;
hdlc = &fc->hdlc[(bch->nr - 1) & 1];
pr_debug("%s: ch%d stat %#x\n", fc->name, bch->nr, stat);
@@ -546,6 +569,12 @@ HDLC_irq(struct bchannel *bch, u32 stat)
write_ctrl(bch, 1);
if (bch->rx_skb)
skb_trim(bch->rx_skb, 0);
+ if (test_bit(FLG_FIFO_STATUS, &bch->Flags)) {
+ skb = _alloc_mISDN_skb(PH_CONTROL_IND,
+ HW_FIFO_RDO, 0, NULL, GFP_KERNEL);
+ if (skb)
+ recv_Bchannel_skb(bch, skb);
+ }
} else {
len = (stat & rmlMask) >> 8;
if (!len)
@@ -575,13 +604,22 @@ handle_tx:
*/
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)
+ 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
+ err = HW_FIFO_XDU_DATA;
+ } else {
pr_debug("%s: ch%d XDU no tx_skb Flags(%lx)\n",
fc->name, bch->nr, bch->Flags);
+ err = HW_FIFO_XDU_NODATA;
+ }
+ if (test_bit(FLG_FIFO_STATUS, &bch->Flags)) {
+ skb = _alloc_mISDN_skb(PH_CONTROL_IND, err,
+ 0, NULL, GFP_KERNEL);
+ if (skb)
+ recv_Bchannel_skb(bch, skb);
+ }
if (bch->tx_skb && bch->tx_skb->len) {
if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
bch->tx_idx = 0;
@@ -721,6 +759,24 @@ avm_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
NULL, GFP_KERNEL);
ret = 0;
break;
+ case PH_CONTROL_REQ:
+ switch (hh->id) {
+ case HW_FIFO_STATUS_ON:
+ test_and_set_bit(FLG_FIFO_STATUS, &bch->Flags);
+ id = 0;
+ break;
+ case HW_FIFO_STATUS_OFF:
+ test_and_clear_bit(FLG_FIFO_STATUS, &bch->Flags);
+ id = 0;
+ break;
+ default:
+ pr_info("PH_CONTROL_REQ %x not supported\n", hh->id);
+ id = -EINVAL;
+ break;
+ }
+ _queue_data(ch, PH_CONTROL_CNF, id, 0, NULL, GFP_KERNEL);
+ ret = 0;
+ break;
}
if (!ret)
dev_kfree_skb(skb);
@@ -835,12 +891,39 @@ init_card(struct fritzcard *fc)
static int
channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
{
- int ret = 0, o1, o2;
+ int ret = 0, o1, o2, idx;
+ u8 *p;
struct fritzcard *fc = bch->hw;
+ idx = (bch->nr - 1) & 1;
switch (cq->op) {
case MISDN_CTRL_GETOP:
- cq->op = MISDN_CTRL_RX_BUFFER;
+ cq->op = MISDN_CTRL_RX_BUFFER |
+ MISDN_CTRL_RX_OFF | MISDN_CTRL_FILL_EMPTY;
+ break;
+ case MISDN_CTRL_RX_OFF: /* turn off / on rx stream */
+ o1 = fc->dropcnt[idx];
+ if (cq->p1) {
+ test_and_set_bit(FLG_RX_OFF, &bch->Flags);
+ fc->dropcnt[idx] = 0;
+ } else
+ test_and_clear_bit(FLG_RX_OFF, &bch->Flags);
+ cq->p2 = o1;
+ if (debug & DEBUG_HW_BCHANNEL)
+ printk(KERN_DEBUG "Bch%d RX %s\n",
+ bch->nr, cq->p1 ? "off" : "on");
+ break;
+ case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */
+ p = fc->fill + (idx * HDLC_FIFO_SIZE_V2);
+ if (cq->p1) {
+ test_and_set_bit(FLG_FILLEMPTY, &bch->Flags);
+ if (cq->p2 > -1)
+ memset(p, cq->p2 & 0xff, HDLC_FIFO_SIZE_V2);
+ } else
+ test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
+ if (debug & DEBUG_HW_BCHANNEL)
+ printk(KERN_DEBUG "FILL_EMPTY Bch%d %s val %02x\n",
+ bch->nr, cq->p1 ? "on" : "off", *p);
break;
case MISDN_CTRL_RX_BUFFER:
/* We return the old values */
diff --git a/drivers/isdn/mISDN/hwchannel.c b/drivers/isdn/mISDN/hwchannel.c
index 467518c..84fbcf1 100644
--- a/drivers/isdn/mISDN/hwchannel.c
+++ b/drivers/isdn/mISDN/hwchannel.c
@@ -135,6 +135,7 @@ 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_RX_OFF, &ch->Flags);
}
EXPORT_SYMBOL(mISDN_clear_bchannel);
diff --git a/include/linux/mISDNhw.h b/include/linux/mISDNhw.h
index 4f97bd3..9776edd 100644
--- a/include/linux/mISDNhw.h
+++ b/include/linux/mISDNhw.h
@@ -73,7 +73,9 @@
#define FLG_LL_OK 24
#define FLG_LL_CONN 25
#define FLG_DTMFSEND 26
-
+/* stop sending received data upstream */
+#define FLG_RX_OFF 27
+#define FLG_FIFO_STATUS 28
/* workq events */
#define FLG_RECVQUEUE 30
#define FLG_PHCHANGE 31
diff --git a/include/linux/mISDNif.h b/include/linux/mISDNif.h
index b26de1a..89ce4ec 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 30
+#define MISDN_RELEASE 31
/* primitives for information exchange
* generell format
@@ -158,6 +158,7 @@
#define HFC_VOL_CHANGE_RX 0x2602
#define HFC_SPL_LOOP_ON 0x2603
#define HFC_SPL_LOOP_OFF 0x2604
+
/* for T30 FAX and analog modem */
#define HW_MOD_FRM 0x4000
#define HW_MOD_FRH 0x4001
@@ -171,6 +172,13 @@
#define HW_MOD_READY 0x4014
#define HW_MOD_LASTDATA 0x4015
+/* Debug and status via PH_CONTROL */
+#define HW_FIFO_STATUS_OFF 0x8000
+#define HW_FIFO_STATUS_ON 0x8001
+#define HW_FIFO_RDO 0x8002
+#define HW_FIFO_XDU_DATA 0x8003
+#define HW_FIFO_XDU_NODATA 0x8004
+
/* DSP_TONE_PATT_ON parameter */
#define TONE_OFF 0x0000
#define TONE_GERMAN_DIALTONE 0x0001
--
1.7.3.4
^ permalink raw reply related
* [PATCH 16/28] mISDN: Help to identify L2 issues
From: Karsten Keil @ 2012-03-18 13:38 UTC (permalink / raw)
To: David Miller; +Cc: netdev, isdn4linux
With multiple cards is hard to figure out which port cause trouble.
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
* [PATCH 05/28] mISDN: Using FLG_ACTIVE flag to determine if layer 1 is active or not.
From: Karsten Keil @ 2012-03-17 9:41 UTC (permalink / raw)
To: David Miller; +Cc: netdev, isdn4linux
From: Andreas Eversberg <andreas@eversberg.eu>
Signed-off-by: Andreas Eversberg <andreas@eversberg.eu>
Signed-off-by: Karsten Keil <keil@b1-systems.de>
---
drivers/isdn/hardware/mISDN/hfcmulti.c | 25 ++++++++++---------------
1 files changed, 10 insertions(+), 15 deletions(-)
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index c4e7fda..cc978e8 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -1619,10 +1619,16 @@ hfcmulti_leds(struct hfc_multi *hc)
* 2 red steady: TE mode deactivate
* left green: L1 active
* left red: frame sync, but no L1
- * right green: L2 active
+ * todo right green: L2 active
*/
- if (hc->chan[hc->dslot].sync != 2) { /* no frame sync */
- if (hc->chan[hc->dslot].dch->dev.D.protocol
+ dch = hc->chan[hc->dslot].dch;
+ if (test_bit(FLG_ACTIVE, &dch->Flags)) {
+ led[0] = 0;
+ led[1] = 0;
+ led[2] = 0;
+ led[3] = 1;
+ } else {
+ if (dch->dev.D.protocol
!= ISDN_P_NT_E1) {
led[0] = 1;
led[1] = 1;
@@ -1635,12 +1641,6 @@ hfcmulti_leds(struct hfc_multi *hc)
}
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 */
@@ -4062,14 +4062,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__);
--
1.7.3.4
^ permalink raw reply related
* [PATCH 03/28] mISDN: Fixed false interruption of audio during bridging change.
From: Karsten Keil @ 2012-03-17 9:34 UTC (permalink / raw)
To: David Miller; +Cc: netdev, isdn4linux
From: Andreas Eversberg <jolly@eversberg.eu>
Transmitted audio data was interrupted if a bridge was enabled or disabled.
Now transmission seamlessly continues during that action.
Fix in hfcmulti.ko
Signed-off-by: Andreas Eversberg <jolly@eversberg.eu>
Signed-off-by: Karsten Keil <keil@b1-systems.de>
---
drivers/isdn/hardware/mISDN/hfcmulti.c | 24 ++++++++++++++++--------
1 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index 0332231..c4e7fda 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -3018,8 +3018,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 +3041,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 +3063,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 +3081,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] |=
--
1.7.3.4
^ permalink raw reply related
* [PATCH 06/28] mISDN: Rework of LED status display for HFC-4S/8S/E1 cards.
From: Karsten Keil @ 2012-03-17 9:55 UTC (permalink / raw)
To: David Miller; +Cc: netdev, isdn4linux
From: Andreas Eversberg <jolly@eversberg.eu>
LEDs will show RED if layer 1 is disabled or fails.
LEDs will show GREEN if layer 1 is active.
LEDs will blink if traffic on D-channel.
Signed-off-by: Andreas Eversberg <jolly@eversberg.eu>
Signed-off-by: Karsten Keil <keil@b1-systems.de>
---
drivers/isdn/hardware/mISDN/hfc_multi.h | 9 +-
drivers/isdn/hardware/mISDN/hfcmulti.c | 157 ++++++++++++++++++-------------
2 files changed, 95 insertions(+), 71 deletions(-)
diff --git a/drivers/isdn/hardware/mISDN/hfc_multi.h b/drivers/isdn/hardware/mISDN/hfc_multi.h
index b0588ac..09e4e77 100644
--- a/drivers/isdn/hardware/mISDN/hfc_multi.h
+++ b/drivers/isdn/hardware/mISDN/hfc_multi.h
@@ -205,18 +205,19 @@ 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 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 */
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index cc978e8..876f7d0 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -1607,40 +1607,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
- * todo 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
*/
+ led[0] = 0;
+ led[1] = 0;
+ led[2] = 0;
+ led[3] = 0;
dch = hc->chan[hc->dslot].dch;
- if (test_bit(FLG_ACTIVE, &dch->Flags)) {
- led[0] = 0;
- led[1] = 0;
- led[2] = 0;
- led[3] = 1;
- } else {
- if (dch->dev.D.protocol
- != ISDN_P_NT_E1) {
- led[0] = 1;
+ if (dch) {
+ if (hc->chan[hc->dslot].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;
}
leds = (led[0] | (led[1]<<2) | (led[2]<<1) | (led[3]<<3))^0xF;
/* leds are inverted */
@@ -1651,9 +1657,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 +1675,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 +1721,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 +1739,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 +1767,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 +1785,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 +1813,8 @@ hfcmulti_leds(struct hfc_multi *hc)
}
break;
}
+ hc->activity_tx = 0;
+ hc->activity_rx = 0;
}
/*
* read dtmf coefficients
@@ -2093,7 +2114,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;
@@ -2236,7 +2258,8 @@ next_frame:
}
}
/* 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)) {
--
1.7.3.4
^ permalink raw reply related
* [PATCH 11/28] mISDN: Add PCM only B-channel protocol to socket functions
From: Karsten Keil @ 2012-03-17 14:59 UTC (permalink / raw)
To: David Miller; +Cc: netdev, isdn4linux
Signed-off-by: Karsten Keil <keil@b1-systems.de>
---
drivers/isdn/mISDN/socket.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
index 1254d8d..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:
@@ -801,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:
--
1.7.3.4
^ permalink raw reply related
* [PATCH 08/28] mISDN: Fix division by zero
From: Karsten Keil @ 2012-03-17 10:03 UTC (permalink / raw)
To: David Miller; +Cc: netdev, isdn4linux
If DTMF debug is set and tresh goes under 100, the printk will cause
a division by zero.
Signed-off-by: Karsten Keil <kkeil@linux-pingi.de>
---
drivers/isdn/mISDN/dsp_dtmf.c | 19 ++++++++++++++-----
1 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/drivers/isdn/mISDN/dsp_dtmf.c b/drivers/isdn/mISDN/dsp_dtmf.c
index 887860b..642f30b 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;
--
1.7.3.4
^ permalink raw reply related
* [PATCH 10/28] mISDN: Add interface for PCM only access
From: Karsten Keil @ 2012-03-17 14:54 UTC (permalink / raw)
To: David Miller; +Cc: netdev, isdn4linux
Sometimes the ISDN chip only control the D-channel
and B-channel are only accessed via the PCM interface.
Add infrastruckture for this mode.
Signed-off-by: Karsten Keil <kkeil@linux-pingi.de>
---
drivers/isdn/mISDN/socket.c | 1 +
include/linux/mISDNhw.h | 3 +++
include/linux/mISDNif.h | 13 +++++++++----
3 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
index abe2d69..1254d8d 100644
--- a/drivers/isdn/mISDN/socket.c
+++ b/drivers/isdn/mISDN/socket.c
@@ -544,6 +544,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:
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
* [PATCH 02/28] mISDN: Fixed hardware bridging/conference check routine of mISDN_dsp.ko.
From: Karsten Keil @ 2012-03-17 9:29 UTC (permalink / raw)
To: David Miller; +Cc: netdev, isdn4linux
From: Andreas Eversberg <jolly@eversberg.eu>
In come cases the hardware bridging/conference (2-n parties) was selected,
but still pure software bridging/conference was used.
Signed-off-by: Andreas Eversberg <jolly@eversberg.eu>
Signed-off-by: Karsten Keil <keil@b1-systems.de>
---
drivers/isdn/mISDN/dsp_cmx.c | 15 ++++++++++-----
1 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c
index b7589c2..0c104b9 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;
}
--
1.7.3.4
^ permalink raw reply related
* [PATCH 07/28] mISDN: Added support for fragmentation of E1 interfaces of hfcmulti driver.
From: Karsten Keil @ 2012-03-17 10:01 UTC (permalink / raw)
To: David Miller; +Cc: netdev, isdn4linux
From: Andreas Eversberg <jolly@eversberg.eu>
Fragmentation is usefull if multiple devices are connected to an E1
interface. Each fragment will have a subset of the available timeslots.
These devices require a cascde connection or a multiplexer.
Signed-off-by: Andreas Eversberg <jolly@eversberg.eu>
Signed-off-by: Karsten Keil <keil@b1-systems.de>
---
drivers/isdn/hardware/mISDN/hfc_multi.h | 6 +-
drivers/isdn/hardware/mISDN/hfcmulti.c | 396 ++++++++++++++++++-------------
2 files changed, 236 insertions(+), 166 deletions(-)
diff --git a/drivers/isdn/hardware/mISDN/hfc_multi.h b/drivers/isdn/hardware/mISDN/hfc_multi.h
index 09e4e77..c601f88 100644
--- a/drivers/isdn/hardware/mISDN/hfc_multi.h
+++ b/drivers/isdn/hardware/mISDN/hfc_multi.h
@@ -208,7 +208,10 @@ struct hfc_multi {
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 */
@@ -234,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 876f7d0..4301331 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 */
@@ -1619,9 +1634,9 @@ hfcmulti_leds(struct hfc_multi *hc)
led[1] = 0;
led[2] = 0;
led[3] = 0;
- dch = hc->chan[hc->dslot].dch;
+ dch = hc->chan[hc->dnum[0]].dch;
if (dch) {
- if (hc->chan[hc->dslot].los)
+ if (hc->chan[hc->dnum[0]].los)
led[1] = 1;
if (hc->e1_state != 1) {
led[0] = 1;
@@ -2453,55 +2468,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)
@@ -2510,10 +2525,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;
@@ -2524,7 +2539,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:
@@ -2535,7 +2550,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:
@@ -2545,7 +2560,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);
@@ -2555,7 +2570,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;
}
@@ -2696,7 +2711,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) {
@@ -2771,7 +2786,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) {
@@ -2781,23 +2796,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);
}
@@ -3870,31 +3888,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 {
@@ -3907,12 +3931,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) {
@@ -3975,13 +3999,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;
@@ -3992,8 +4017,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 */
@@ -4571,6 +4594,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
@@ -4626,7 +4651,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);
@@ -4648,15 +4674,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)
@@ -4667,15 +4697,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)
@@ -4693,61 +4719,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) {
@@ -4763,7 +4737,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 */
@@ -4773,7 +4747,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) {
@@ -4782,7 +4756,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) {
@@ -4792,7 +4766,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) {
@@ -4802,7 +4776,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)) {
@@ -4811,7 +4785,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"
@@ -4843,20 +4817,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);
+ 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);
@@ -4989,7 +5028,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",
@@ -5023,18 +5063,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;
@@ -5117,23 +5175,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 */
--
1.7.3.4
^ permalink raw reply related
* [PATCH 12/28] mISDN: L2 timeouts need to be queued as L2 event
From: Karsten Keil @ 2012-03-17 15:01 UTC (permalink / raw)
To: David Miller; +Cc: netdev, isdn4linux
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
* [PATCH 14/28] mISDN: Layer1 statemachine fix
From: Karsten Keil @ 2012-03-17 15:07 UTC (permalink / raw)
To: David Miller; +Cc: netdev, isdn4linux
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 65912bd..7feb78a 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
* [PATCH 04/28] mISDN: Added PH_* state info to tei manager.
From: Karsten Keil @ 2012-03-17 9:38 UTC (permalink / raw)
To: David Miller; +Cc: netdev, isdn4linux
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
* [PATCH 01/28] mISDN: Fix NULL pointer bug in if-condition of mISDN_dsp
From: Karsten Keil @ 2012-03-17 9:27 UTC (permalink / raw)
To: David Miller; +Cc: netdev, isdn4linux
From: Andreas Eversberg <jolly@eversberg.eu>
Fix bug in cases where dsp->conf was NULL.
Signed-off-by: Andreas Eversberg <jolly@eversberg.eu>
Signed-off-by: Karsten Keil <keil@b1-systems.de>
---
drivers/isdn/mISDN/dsp_cmx.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c
index 334feab..b7589c2 100644
--- a/drivers/isdn/mISDN/dsp_cmx.c
+++ b/drivers/isdn/mISDN/dsp_cmx.c
@@ -1328,7 +1328,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;
}
--
1.7.3.4
^ permalink raw reply related
* Re: [PATCH v5 2/3] netdev/of/phy: Add MDIO bus multiplexer support.
From: David Daney @ 2012-04-23 16:41 UTC (permalink / raw)
To: David Miller
Cc: david.s.daney, ddaney.cavm, grant.likely, rob.herring,
devicetree-discuss, netdev, linux-kernel, linux-mips, afleming,
galak
In-Reply-To: <20120421.190335.1197591560590885057.davem@davemloft.net>
On 04/21/2012 04:03 PM, David Miller wrote:
> From: David Daney<david.s.daney@gmail.com>
> Date: Sat, 21 Apr 2012 14:25:51 -0700
>
>> If we were to specify the dependencies in both places, we gain nothing
>> other than duplication of information.
>
> Each Kconfig option enabling a module has to have appropriate
> dependencies.
>
I will send a revised patch set.
Thanks,
David Daney
^ permalink raw reply
* Re: linux-next: Tree for Apr 23 (phonet sysctl)
From: Randy Dunlap @ 2012-04-23 16:38 UTC (permalink / raw)
To: Stephen Rothwell; +Cc: linux-next, LKML, ebiederm, netdev
In-Reply-To: <20120423170701.c96e402234b1387dece11dda@canb.auug.org.au>
On 04/23/2012 12:07 AM, Stephen Rothwell wrote:
> Hi all,
>
> Changes since 20120420:
ERROR: "unregister_net_sysctl_table" [net/phonet/phonet.ko] undefined!
ERROR: "register_net_sysctl" [net/phonet/phonet.ko] undefined!
when CONFIG_SYSCTL is not enabled.
--
~Randy
^ permalink raw reply
* Re: [PATCH 2/3] don't take cgroup_mutex in destroy()
From: Glauber Costa @ 2012-04-23 16:36 UTC (permalink / raw)
To: Li Zefan
Cc: Tejun Heo, netdev-u79uwXL29TY76Z2rM5mHXA,
cgroups-u79uwXL29TY76Z2rM5mHXA,
kamezawa.hiroyu-+CUm20s59erQFUHtdCDX3A, David Miller,
devel-GEFAQzZX7r8dnm+yROfE0A, Vivek Goyal
In-Reply-To: <4F9257F4.2070505-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
On 04/21/2012 03:47 AM, Li Zefan wrote:
> Glauber Costa wrote:
>
>> On 04/19/2012 07:57 PM, Tejun Heo wrote:
>>> On Thu, Apr 19, 2012 at 07:49:17PM -0300, Glauber Costa wrote:
>>>> Most of the destroy functions are only doing very simple things
>>>> like freeing memory.
>>>>
>>>> The ones who goes through lists and such, already use its own
>>>> locking for those.
>>>>
>>>> * The cgroup itself won't go away until we free it, (after destroy)
>>>> * The parent won't go away because we hold a reference count
>>>> * There are no more tasks in the cgroup, and the cgroup is declared
>>>> dead (cgroup_is_removed() == true)
>>>>
>>>> For the blk-cgroup and the cpusets, I got the impression that the mutex
>>>> is still necessary.
>>>>
>>>> For those, I grabbed it from within the destroy function itself.
>>>>
>>>> If the maintainer for those subsystems consider it safe to remove
>>>> it, we can discuss it separately.
>>>
>>> I really don't like cgroup_lock() usage spreading more. It's
>>> something which should be contained in cgroup.c proper. I looked at
>>> the existing users a while ago and they seemed to be compensating
>>> deficencies in API, so, if at all possible, let's not spread the
>>> disease.
>>
>> Well, I can dig deeper and see if they are really needed. I don't know cpusets and blkcg *that* well, that's why I took them there, hoping that someone could enlighten me, maybe they aren't really needed even now.
>>
>> I agree with the compensating: As I mentioned, most of them are already taking other kinds of lock to protect their structures, which is the right thing to do.
>>
>> There were only two or three spots in cpusets and blkcg where I wasn't that sure that we could drop the lock... What do you say about that ?
>> .
>
> We can drop cgroup_mutex for cpusets with changes like this:
>
> (Note: as I'm not able to get the latest code at this momment, this patch is based on 3.0.)
>
> There are several places reading number_of_cpusets, but no one holds cgroup_mutex, except
> the one in generate_sched_domains(). With this patch, both cpuset_create() and
> generate_sched_domains() are still holding cgroup_mutex, so it's safe.
>
> --- linux-kernel/kernel/cpuset.c.orig 2012-04-21 01:55:57.000000000 -0400
> +++ linux-kernel/kernel/cpuset.c 2012-04-21 02:30:53.000000000 -0400
> @@ -1876,7 +1876,9 @@ static struct cgroup_subsys_state *cpuse
> cs->relax_domain_level = -1;
>
> cs->parent = parent;
> + mutex_lock(&callback_mutex);
> number_of_cpusets++;
> + mutex_unlock(&callback_mutex);
> return&cs->css ;
> }
>
> @@ -1890,10 +1892,18 @@ static void cpuset_destroy(struct cgroup
> {
> struct cpuset *cs = cgroup_cs(cont);
>
> - if (is_sched_load_balance(cs))
> + if (is_sched_load_balance(cs)) {
> + /*
> + * This cpuset is under destruction, so no one else can
> + * modify it, so it's safe to call update_flag() without
> + * cgroup_lock.
> + */
> update_flag(CS_SCHED_LOAD_BALANCE, cs, 0);
> + }
>
> + mutex_lock(&callback_mutex);
> number_of_cpusets--;
> + mutex_lock(&callback_mutex);
> free_cpumask_var(cs->cpus_allowed);
> kfree(cs);
> }
I'll see if I can work something out.
^ permalink raw reply
* Re: linux-next: Tree for Apr 23 (ax.25 sysctl)
From: Randy Dunlap @ 2012-04-23 16:25 UTC (permalink / raw)
To: Stephen Rothwell; +Cc: linux-next, LKML, netdev, linux-hams, Ralf Baechle
In-Reply-To: <20120423170701.c96e402234b1387dece11dda@canb.auug.org.au>
On 04/23/2012 12:07 AM, Stephen Rothwell wrote:
> Hi all,
>
> Changes since 20120420:
include/net/ax25.h:447:75: error: expected ';' before '}' token
static inline int ax25_register_dev_sysctl(ax25_dev *ax25_dev) { return 0 };
static inline void ax25_unregister_dev_sysctl(ax25_dev *ax25_dev) {};
Is this from Eric B.'s sysctl patches?
First function: move ';' inside braces.
Second function: drop the ';'.
--
~Randy
^ permalink raw reply
* Re: [net-next PATCH] net: dcb: add CEE notify calls
From: John Fastabend @ 2012-04-23 16:12 UTC (permalink / raw)
To: Shmulik Ravid; +Cc: davem, netdev, eilong, amirv
In-Reply-To: <1335200401.15423.18.camel@lb-tlvb-shmulik.il.broadcom.com>
On 4/23/2012 10:00 AM, Shmulik Ravid wrote:
>
>> No. We want all the firmware agents and host based agents to look the
>> same from the application. The situation you described is exactly the
>> same for user space as in firmware. The DCBx state machine starts and may
>> call dcbnl_setxxx with initial (local) values. At some later point these
>> may change (possibly because of negotiation with a peer) and we need to
>> call dcbnl_setxxx again.
>>
>> I don't see how this complicates any user mode code? Presumably the agent
>> is listening to DCBx events because it really wants to know the current
>> state of DCBx. It seems to me skipping notifications will actually cause
>> more issues this results in the hardware being in some state that did not
>> trigger any events and the agent will now be out of sync. This is the
>> problem I am trying to solve.
>>
>> btw with this patch we can remove the notify calls in bnx2x.
>>
>> .John
>>
> OK, I see.
>>From a user mode application monitoring the netlink notification you get
> successive updates each indicating the current valid negotiated
> parameters (and HW state) and that's fine.
> However I don't see how you can remove the notification call form the
> bnx2x. When the FW DCBx agent decides to change the negotiated
> parameters (perhaps in response to a peer request), it alerts the driver
> which configures the HW and then needs to somehow notify the user about
> the newly negotiated parameters.
>
You are right here. I guess only the notify call after setapp can be removed.
Can you ACK the patch to indicate this addresses your concerns?
.John
> Shmulik
>
>
^ permalink raw reply
* It's here...video 2 tells it all
From: John @ 2012-04-23 14:26 UTC (permalink / raw)
To: netdev
Hi,
It's been a crazy couple of days here which is
why I'm emailing you on a Saturday night.
We've been inundated with e-mails about
Video 1...thank you for the hundreds of responses
and comments!
We've got Video 2 loaded up for you...
your world is about to be rocked.
http://www.boldstatementmarketing.com/vmme-a-2/
--> See step-by-step how to make sales
videos that will bring new business to you
like flies to honey.
--> Watch how I easily create a cool,
pro video from my home laptop...it's so
easy you'll be in awe!
--> Know what steps you can take to
use video to grow your business
faster than any other marketing
If you've ever struggled with getting
more clients or customers, you can
breath a HUGE SIGH OF RELIEF.
Your struggle is over. Watch video 2
http://www.boldstatementmarketing.com/vmme-a-2/
All the best,
John
PS: Video 1 is there for you too in case you
missed it. I'm working on Video 3 in the 4 Video
fr.ee course. Video 3 is all about marketing with
the videos I'm showing you how to make. Leave
a comment/question and let me know what you
think and what you need to know to prosper in
your business with this information.
http://www.boldstatementmarketing.com/vmme-a-2/
^ permalink raw reply
* [PATCH net] net/neigh: move neigh cleanup routine to neigh_destroy
From: Or Gerlitz @ 2012-04-23 15:34 UTC (permalink / raw)
To: davem; +Cc: netdev, Or Gerlitz, Shlomo Pongratz
From: Shlomo Pongratz <shlomop@mellanox.com>
Move call the neigh_cleanup call to be done from neigh_destroy, this
ensures the cleanup callback is invoked only when the neighbour reference
count becomes zero (e.g in the same manner as ndo_neigh_destory).
Note that with this change neigh_destroy will truly revert the action of
neigh_create, as neigh_release which calls neigh_destroy is called directly
from various code paths, and thus neigh->parms->neigh_cleanup is not called
for these code paths.
Also, with commit 7d26bb103 "bonding: emit event when bonding changes MAC" that
triggers netdev address change event, a race was introduced since neigh cleanup
can be called when there's reference on the neighbour.
Signed-off-by: Shlomo Pongratz <shlomop@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
---
net/core/neighbour.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 0a68045..f4a4e64 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -106,9 +106,6 @@ static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb)
static void neigh_cleanup_and_release(struct neighbour *neigh)
{
- if (neigh->parms->neigh_cleanup)
- neigh->parms->neigh_cleanup(neigh);
-
__neigh_notify(neigh, RTM_DELNEIGH, 0);
neigh_release(neigh);
}
@@ -724,6 +721,9 @@ void neigh_destroy(struct neighbour *neigh)
skb_queue_purge(&neigh->arp_queue);
neigh->arp_queue_len_bytes = 0;
+ if (neigh->parms->neigh_cleanup)
+ neigh->parms->neigh_cleanup(neigh);
+
if (dev->netdev_ops->ndo_neigh_destroy)
dev->netdev_ops->ndo_neigh_destroy(neigh);
--
1.7.1
^ permalink raw reply related
* Bug#656476: Sundance network driver (D-Link DFE-580TX) timeouts rendering interface unusable
From: Mike . @ 2012-04-23 15:34 UTC (permalink / raw)
To: jrnieder, 656476
Cc: eric.dumazet, ben, kirjanov, netdev, benoit.mortier, herbert
In-Reply-To: <20120316220413.GA31359@burratino>
[-- Attachment #1: Type: text/plain, Size: 2109 bytes --]
Hi,
Sorry for the delay, couldn't test for quite some time due to some fried hardware, kernel.org bug report has been created now : https://bugzilla.kernel.org/show_bug.cgi?id=43152
Cheers,
Mike.
> Date: Fri, 16 Mar 2012 17:04:13 -0500
> From: jrnieder@gmail.com
> To: mike-bugreport@hotmail.com
> CC: eric.dumazet@gmail.com; ben@decadent.org.uk; kirjanov@gmail.com; netdev@vger.kernel.org; benoit.mortier@opensides.be; herbert@gondor.apana.org.au
> Subject: Re: Sundance network driver (D-Link DFE-580TX) timeouts rendering interface unusable
>
> Hi again,
>
> Mike . wrote:
>
> >> Oh well, we also must make sure we held np->lock in TX completion when
> >> doing our test to eventually call netif_wake_queue(), I missed it was
> >> released too early.
> >>
> >> here is a more complete patch.
> >
> > I applied the patch, recompiled the module, loaded it into the kernel and
> > started testing traffic on the interface with the following result :
> >
> > [ 1124.008030] ------------[ cut here ]------------
> > [ 1124.008101] WARNING: at /build/buildd-linux-2.6_3.2.1-2-i386-4wAPNj/linux-2.6-3.2.1/debian/build/source_i386_none/net/sched/sch_generic.c:255 dev_watchdog+0xb1/0x104()
> > [ 1124.008201] Hardware name:
> > [ 1124.008252] NETDEV WATCHDOG: eth1 (sundance): transmit queue 0 timed out
> [...]
> > After this the same repeat of transmit timeouts (as posted earlier) in the
> > log untill I down the interface.
>
> Thanks. I assume current 3.3 release candidates behave the same way.
>
> Based on [2], it looks like v2.6.25-rc9~99^2~24 ([NET]: Add preemption
> point in qdisc_run, 2008-03-28) made this easier to trip.
>
> As for the next step: I'd suggest posting a summary of the symptoms,
> which kernel versions you have tested, and a link to [1] at
> http://bugzilla.kernel.org/, product Drivers, component Network, and
> letting us know the bug number so we can track it without forgetting
> what has already been learned.
>
> Hope that helps,
> Jonathan
>
> [1] http://thread.gmane.org/gmane.linux.network/219101
[-- Attachment #2: Type: text/html, Size: 2661 bytes --]
^ permalink raw reply
* Re-profiling funds.
From: Mr.Liu Wang @ 2012-04-23 15:03 UTC (permalink / raw)
I am Mr. Liu Wang, an official with the International bank of Taipei,Taiwan.
I ask for your partnership in re-profiling funds.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox