aboutsummaryrefslogtreecommitdiff
path: root/drivers/isdn/hardware/mISDN/mISDNipac.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/isdn/hardware/mISDN/mISDNipac.c')
-rw-r--r--drivers/isdn/hardware/mISDN/mISDNipac.c255
1 files changed, 123 insertions, 132 deletions
diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c
index 64ecc6f5ffa..ccd7d851be2 100644
--- a/drivers/isdn/hardware/mISDN/mISDNipac.c
+++ b/drivers/isdn/hardware/mISDN/mISDNipac.c
@@ -20,6 +20,7 @@
*
*/
+#include <linux/irqreturn.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/mISDNhw.h>
@@ -128,7 +129,7 @@ isac_empty_fifo(struct isac_hw *isac, int count)
}
if ((isac->dch.rx_skb->len + count) >= isac->dch.maxlen) {
pr_debug("%s: %s overrun %d\n", isac->name, __func__,
- isac->dch.rx_skb->len + count);
+ isac->dch.rx_skb->len + count);
WriteISAC(isac, ISAC_CMDR, 0x80);
return;
}
@@ -139,7 +140,7 @@ isac_empty_fifo(struct isac_hw *isac, int count)
char pfx[MISDN_MAX_IDLEN + 16];
snprintf(pfx, MISDN_MAX_IDLEN + 15, "D-recv %s %d ",
- isac->name, count);
+ isac->name, count);
print_hex_dump_bytes(pfx, DUMP_PREFIX_OFFSET, ptr, count);
}
}
@@ -177,7 +178,7 @@ isac_fill_fifo(struct isac_hw *isac)
char pfx[MISDN_MAX_IDLEN + 16];
snprintf(pfx, MISDN_MAX_IDLEN + 15, "D-send %s %d ",
- isac->name, count);
+ isac->name, count);
print_hex_dump_bytes(pfx, DUMP_PREFIX_OFFSET, ptr, count);
}
}
@@ -282,7 +283,7 @@ isac_mos_irq(struct isac_hw *isac)
}
isac->mon_rx[isac->mon_rxp++] = ReadISAC(isac, ISAC_MOR0);
pr_debug("%s: ISAC MOR0 %02x\n", isac->name,
- isac->mon_rx[isac->mon_rxp - 1]);
+ isac->mon_rx[isac->mon_rxp - 1]);
if (isac->mon_rxp == 1) {
isac->mocr |= 0x04;
WriteISAC(isac, ISAC_MOCR, isac->mocr);
@@ -312,7 +313,7 @@ afterMONR0:
}
isac->mon_rx[isac->mon_rxp++] = ReadISAC(isac, ISAC_MOR1);
pr_debug("%s: ISAC MOR1 %02x\n", isac->name,
- isac->mon_rx[isac->mon_rxp - 1]);
+ isac->mon_rx[isac->mon_rxp - 1]);
isac->mocr |= 0x40;
WriteISAC(isac, ISAC_MOCR, isac->mocr);
}
@@ -324,7 +325,7 @@ afterMONR1:
WriteISAC(isac, ISAC_MOCR, isac->mocr);
if (isac->monitor) {
ret = isac->monitor(isac->dch.hw, MONITOR_RX_0,
- isac->mon_rx, isac->mon_rxp);
+ isac->mon_rx, isac->mon_rxp);
if (ret)
kfree(isac->mon_rx);
} else {
@@ -342,7 +343,7 @@ afterMONR1:
WriteISAC(isac, ISAC_MOCR, isac->mocr);
if (isac->monitor) {
ret = isac->monitor(isac->dch.hw, MONITOR_RX_1,
- isac->mon_rx, isac->mon_rxp);
+ isac->mon_rx, isac->mon_rxp);
if (ret)
kfree(isac->mon_rx);
} else {
@@ -355,7 +356,7 @@ afterMONR1:
}
if (val & 0x02) {
if ((!isac->mon_tx) || (isac->mon_txc &&
- (isac->mon_txp >= isac->mon_txc) && !(val & 0x08))) {
+ (isac->mon_txp >= isac->mon_txc) && !(val & 0x08))) {
isac->mocr &= 0xf0;
WriteISAC(isac, ISAC_MOCR, isac->mocr);
isac->mocr |= 0x0a;
@@ -363,7 +364,7 @@ afterMONR1:
if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
if (isac->monitor)
ret = isac->monitor(isac->dch.hw,
- MONITOR_TX_0, NULL, 0);
+ MONITOR_TX_0, NULL, 0);
}
kfree(isac->mon_tx);
isac->mon_tx = NULL;
@@ -374,7 +375,7 @@ afterMONR1:
if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
if (isac->monitor)
ret = isac->monitor(isac->dch.hw,
- MONITOR_TX_0, NULL, 0);
+ MONITOR_TX_0, NULL, 0);
kfree(isac->mon_tx);
isac->mon_tx = NULL;
isac->mon_txc = 0;
@@ -383,12 +384,12 @@ afterMONR1:
}
WriteISAC(isac, ISAC_MOX0, isac->mon_tx[isac->mon_txp++]);
pr_debug("%s: ISAC %02x -> MOX0\n", isac->name,
- isac->mon_tx[isac->mon_txp - 1]);
+ isac->mon_tx[isac->mon_txp - 1]);
}
AfterMOX0:
if (val & 0x20) {
if ((!isac->mon_tx) || (isac->mon_txc &&
- (isac->mon_txp >= isac->mon_txc) && !(val & 0x80))) {
+ (isac->mon_txp >= isac->mon_txc) && !(val & 0x80))) {
isac->mocr &= 0x0f;
WriteISAC(isac, ISAC_MOCR, isac->mocr);
isac->mocr |= 0xa0;
@@ -396,7 +397,7 @@ AfterMOX0:
if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
if (isac->monitor)
ret = isac->monitor(isac->dch.hw,
- MONITOR_TX_1, NULL, 0);
+ MONITOR_TX_1, NULL, 0);
}
kfree(isac->mon_tx);
isac->mon_tx = NULL;
@@ -407,7 +408,7 @@ AfterMOX0:
if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
if (isac->monitor)
ret = isac->monitor(isac->dch.hw,
- MONITOR_TX_1, NULL, 0);
+ MONITOR_TX_1, NULL, 0);
kfree(isac->mon_tx);
isac->mon_tx = NULL;
isac->mon_txc = 0;
@@ -416,7 +417,7 @@ AfterMOX0:
}
WriteISAC(isac, ISAC_MOX1, isac->mon_tx[isac->mon_txp++]);
pr_debug("%s: ISAC %02x -> MOX1\n", isac->name,
- isac->mon_tx[isac->mon_txp - 1]);
+ isac->mon_tx[isac->mon_txp - 1]);
}
AfterMOX1:
val = 0; /* dummy to avoid warning */
@@ -431,7 +432,7 @@ isac_cisq_irq(struct isac_hw *isac) {
pr_debug("%s: ISAC CIR0 %02X\n", isac->name, val);
if (val & 2) {
pr_debug("%s: ph_state change %x->%x\n", isac->name,
- isac->state, (val >> 2) & 0xf);
+ isac->state, (val >> 2) & 0xf);
isac->state = (val >> 2) & 0xf;
isac_ph_state_change(isac);
}
@@ -450,7 +451,7 @@ isacsx_cic_irq(struct isac_hw *isac)
pr_debug("%s: ISACX CIR0 %02X\n", isac->name, val);
if (val & ISACX_CIR0_CIC0) {
pr_debug("%s: ph_state change %x->%x\n", isac->name,
- isac->state, val >> 4);
+ isac->state, val >> 4);
isac->state = val >> 4;
isac_ph_state_change(isac);
}
@@ -487,7 +488,7 @@ isacsx_rme_irq(struct isac_hw *isac)
if (isac->dch.rx_skb) {
skb_trim(isac->dch.rx_skb, isac->dch.rx_skb->len - 1);
pr_debug("%s: dchannel received %d\n", isac->name,
- isac->dch.rx_skb->len);
+ isac->dch.rx_skb->len);
recv_Dchannel(&isac->dch);
}
}
@@ -602,10 +603,11 @@ isac_l1hw(struct mISDNchannel *ch, struct sk_buff *skb)
}
static int
-isac_ctrl(struct isac_hw *isac, u32 cmd, u_long para)
+isac_ctrl(struct isac_hw *isac, u32 cmd, unsigned long para)
{
u8 tl = 0;
- u_long flags;
+ unsigned long flags;
+ int ret = 0;
switch (cmd) {
case HW_TESTLOOP:
@@ -625,12 +627,15 @@ isac_ctrl(struct isac_hw *isac, u32 cmd, u_long para)
}
spin_unlock_irqrestore(isac->hwlock, flags);
break;
+ case HW_TIMER3_VALUE:
+ ret = l1_event(isac->dch.l1, HW_TIMER3_VALUE | (para & 0xff));
+ break;
default:
pr_debug("%s: %s unknown command %x %lx\n", isac->name,
- __func__, cmd, para);
- return -1;
+ __func__, cmd, para);
+ ret = -1;
}
- return 0;
+ return ret;
}
static int
@@ -684,16 +689,16 @@ isac_l1cmd(struct dchannel *dch, u32 cmd)
case PH_ACTIVATE_IND:
test_and_set_bit(FLG_ACTIVE, &dch->Flags);
_queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL,
- GFP_ATOMIC);
+ GFP_ATOMIC);
break;
case PH_DEACTIVATE_IND:
test_and_clear_bit(FLG_ACTIVE, &dch->Flags);
_queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL,
- GFP_ATOMIC);
+ GFP_ATOMIC);
break;
default:
pr_debug("%s: %s unknown command %x\n", isac->name,
- __func__, cmd);
+ __func__, cmd);
return -1;
}
return 0;
@@ -730,7 +735,7 @@ dbusy_timer_handler(struct isac_hw *isac)
rbch = ReadISAC(isac, ISAC_RBCH);
star = ReadISAC(isac, ISAC_STAR);
pr_debug("%s: D-Channel Busy RBCH %02x STAR %02x\n",
- isac->name, rbch, star);
+ isac->name, rbch, star);
if (rbch & ISAC_RBCH_XAC) /* D-Channel Busy */
test_and_set_bit(FLG_L1_BUSY, &isac->dch.Flags);
else {
@@ -752,7 +757,7 @@ static int
open_dchannel(struct isac_hw *isac, struct channel_req *rq)
{
pr_debug("%s: %s dev(%d) open from %p\n", isac->name, __func__,
- isac->dch.dev.id, __builtin_return_address(1));
+ isac->dch.dev.id, __builtin_return_address(1));
if (rq->protocol != ISDN_P_TE_S0)
return -EINVAL;
if (rq->adr.channel == 1)
@@ -762,7 +767,7 @@ open_dchannel(struct isac_hw *isac, struct channel_req *rq)
rq->ch->protocol = rq->protocol;
if (isac->dch.state == 7)
_queue_data(rq->ch, PH_ACTIVATE_IND, MISDN_ID_ANY,
- 0, NULL, GFP_KERNEL);
+ 0, NULL, GFP_KERNEL);
return 0;
}
@@ -806,7 +811,7 @@ isac_init(struct isac_hw *isac)
val = ReadISAC(isac, ISACX_ID);
if (isac->dch.debug & DEBUG_HW)
pr_notice("%s: ISACX Design ID %x\n",
- isac->name, val & 0x3f);
+ isac->name, val & 0x3f);
val = ReadISAC(isac, ISACX_CIR0);
pr_debug("%s: ISACX CIR0 %02X\n", isac->name, val);
isac->state = val >> 4;
@@ -831,7 +836,7 @@ isac_init(struct isac_hw *isac)
val = ReadISAC(isac, ISAC_RBCH);
if (isac->dch.debug & DEBUG_HW)
pr_notice("%s: ISAC version (%x): %s\n", isac->name,
- val, ISACVer[(val >> 5) & 3]);
+ val, ISACVer[(val >> 5) & 3]);
isac->type |= ((val >> 5) & 3);
if (!isac->adf2)
isac->adf2 = 0x80;
@@ -888,7 +893,7 @@ waitforCEC(struct hscx_hw *hx)
}
if (to < 50)
pr_debug("%s: B%1d CEC %d us\n", hx->ip->name, hx->bch.nr,
- 50 - to);
+ 50 - to);
if (!to)
pr_info("%s: B%1d CEC timeout\n", hx->ip->name, hx->bch.nr);
}
@@ -908,7 +913,7 @@ waitforXFW(struct hscx_hw *hx)
}
if (to < 50)
pr_debug("%s: B%1d XFW %d us\n", hx->ip->name, hx->bch.nr,
- 50 - to);
+ 50 - to);
if (!to)
pr_info("%s: B%1d XFW timeout\n", hx->ip->name, hx->bch.nr);
}
@@ -928,38 +933,37 @@ static void
hscx_empty_fifo(struct hscx_hw *hscx, u8 count)
{
u8 *p;
+ int maxlen;
pr_debug("%s: B%1d %d\n", hscx->ip->name, hscx->bch.nr, count);
- if (!hscx->bch.rx_skb) {
- hscx->bch.rx_skb = mI_alloc_skb(hscx->bch.maxlen, GFP_ATOMIC);
- if (!hscx->bch.rx_skb) {
- pr_info("%s: B receive out of memory\n",
- hscx->ip->name);
- hscx_cmdr(hscx, 0x80); /* RMC */
- return;
- }
+ if (test_bit(FLG_RX_OFF, &hscx->bch.Flags)) {
+ hscx->bch.dropcnt += count;
+ hscx_cmdr(hscx, 0x80); /* RMC */
+ return;
}
- if ((hscx->bch.rx_skb->len + count) > hscx->bch.maxlen) {
- pr_debug("%s: overrun %d\n", hscx->ip->name,
- hscx->bch.rx_skb->len + count);
- skb_trim(hscx->bch.rx_skb, 0);
+ maxlen = bchannel_get_rxbuf(&hscx->bch, count);
+ if (maxlen < 0) {
hscx_cmdr(hscx, 0x80); /* RMC */
+ if (hscx->bch.rx_skb)
+ skb_trim(hscx->bch.rx_skb, 0);
+ pr_warning("%s.B%d: No bufferspace for %d bytes\n",
+ hscx->ip->name, hscx->bch.nr, count);
return;
}
p = skb_put(hscx->bch.rx_skb, count);
if (hscx->ip->type & IPAC_TYPE_IPACX)
hscx->ip->read_fifo(hscx->ip->hw,
- hscx->off + IPACX_RFIFOB, p, count);
+ hscx->off + IPACX_RFIFOB, p, count);
else
hscx->ip->read_fifo(hscx->ip->hw,
- hscx->off, p, count);
+ hscx->off, p, count);
hscx_cmdr(hscx, 0x80); /* RMC */
if (hscx->bch.debug & DEBUG_HW_BFIFO) {
snprintf(hscx->log, 64, "B%1d-recv %s %d ",
- hscx->bch.nr, hscx->ip->name, count);
+ hscx->bch.nr, hscx->ip->name, count);
print_hex_dump_bytes(hscx->log, DUMP_PREFIX_OFFSET, p, count);
}
}
@@ -970,35 +974,41 @@ hscx_fill_fifo(struct hscx_hw *hscx)
int count, more;
u8 *p;
- if (!hscx->bch.tx_skb)
- return;
- count = hscx->bch.tx_skb->len - hscx->bch.tx_idx;
- if (count <= 0)
- return;
- p = hscx->bch.tx_skb->data + hscx->bch.tx_idx;
-
- more = test_bit(FLG_TRANSPARENT, &hscx->bch.Flags) ? 1 : 0;
- if (count > hscx->fifo_size) {
+ if (!hscx->bch.tx_skb) {
+ if (!test_bit(FLG_TX_EMPTY, &hscx->bch.Flags))
+ return;
count = hscx->fifo_size;
more = 1;
- }
- pr_debug("%s: B%1d %d/%d/%d\n", hscx->ip->name, hscx->bch.nr, count,
- hscx->bch.tx_idx, hscx->bch.tx_skb->len);
- hscx->bch.tx_idx += count;
+ p = hscx->log;
+ memset(p, hscx->bch.fill[0], count);
+ } else {
+ count = hscx->bch.tx_skb->len - hscx->bch.tx_idx;
+ if (count <= 0)
+ return;
+ p = hscx->bch.tx_skb->data + hscx->bch.tx_idx;
+ more = test_bit(FLG_TRANSPARENT, &hscx->bch.Flags) ? 1 : 0;
+ if (count > hscx->fifo_size) {
+ count = hscx->fifo_size;
+ more = 1;
+ }
+ pr_debug("%s: B%1d %d/%d/%d\n", hscx->ip->name, hscx->bch.nr,
+ count, hscx->bch.tx_idx, hscx->bch.tx_skb->len);
+ hscx->bch.tx_idx += count;
+ }
if (hscx->ip->type & IPAC_TYPE_IPACX)
hscx->ip->write_fifo(hscx->ip->hw,
- hscx->off + IPACX_XFIFOB, p, count);
+ hscx->off + IPACX_XFIFOB, p, count);
else {
waitforXFW(hscx);
hscx->ip->write_fifo(hscx->ip->hw,
- hscx->off, p, count);
+ hscx->off, p, count);
}
hscx_cmdr(hscx, more ? 0x08 : 0x0a);
- if (hscx->bch.debug & DEBUG_HW_BFIFO) {
+ if (hscx->bch.tx_skb && (hscx->bch.debug & DEBUG_HW_BFIFO)) {
snprintf(hscx->log, 64, "B%1d-send %s %d ",
- hscx->bch.nr, hscx->ip->name, count);
+ hscx->bch.nr, hscx->ip->name, count);
print_hex_dump_bytes(hscx->log, DUMP_PREFIX_OFFSET, p, count);
}
}
@@ -1006,17 +1016,17 @@ hscx_fill_fifo(struct hscx_hw *hscx)
static void
hscx_xpr(struct hscx_hw *hx)
{
- if (hx->bch.tx_skb && hx->bch.tx_idx < hx->bch.tx_skb->len)
+ if (hx->bch.tx_skb && hx->bch.tx_idx < hx->bch.tx_skb->len) {
hscx_fill_fifo(hx);
- else {
- if (hx->bch.tx_skb) {
- /* send confirm, on trans, free on hdlc. */
- if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags))
- confirm_Bsend(&hx->bch);
+ } else {
+ if (hx->bch.tx_skb)
dev_kfree_skb(hx->bch.tx_skb);
- }
- if (get_next_bframe(&hx->bch))
+ if (get_next_bframe(&hx->bch)) {
+ hscx_fill_fifo(hx);
+ test_and_clear_bit(FLG_TX_EMPTY, &hx->bch.Flags);
+ } else if (test_bit(FLG_TX_EMPTY, &hx->bch.Flags)) {
hscx_fill_fifo(hx);
+ }
}
}
@@ -1036,18 +1046,18 @@ ipac_rme(struct hscx_hw *hx)
if (!(rstab & 0x80)) {
if (hx->bch.debug & DEBUG_HW_BCHANNEL)
pr_notice("%s: B%1d invalid frame\n",
- hx->ip->name, hx->bch.nr);
+ hx->ip->name, hx->bch.nr);
}
if (rstab & 0x40) {
if (hx->bch.debug & DEBUG_HW_BCHANNEL)
pr_notice("%s: B%1d RDO proto=%x\n",
- hx->ip->name, hx->bch.nr,
- hx->bch.state);
+ hx->ip->name, hx->bch.nr,
+ hx->bch.state);
}
if (!(rstab & 0x20)) {
if (hx->bch.debug & DEBUG_HW_BCHANNEL)
pr_notice("%s: B%1d CRC error\n",
- hx->ip->name, hx->bch.nr);
+ hx->ip->name, hx->bch.nr);
}
hscx_cmdr(hx, 0x80); /* Do RMC */
return;
@@ -1064,11 +1074,11 @@ ipac_rme(struct hscx_hw *hx)
return;
if (hx->bch.rx_skb->len < 2) {
pr_debug("%s: B%1d frame to short %d\n",
- hx->ip->name, hx->bch.nr, hx->bch.rx_skb->len);
+ hx->ip->name, hx->bch.nr, hx->bch.rx_skb->len);
skb_trim(hx->bch.rx_skb, 0);
} else {
skb_trim(hx->bch.rx_skb, hx->bch.rx_skb->len - 1);
- recv_Bchannel(&hx->bch, 0);
+ recv_Bchannel(&hx->bch, 0, false);
}
}
@@ -1085,7 +1095,7 @@ ipac_irq(struct hscx_hw *hx, u8 ista)
if (m & ista) {
exirb = ReadHSCX(hx, IPAC_EXIRB);
pr_debug("%s: B%1d EXIRB %02x\n", hx->ip->name,
- hx->bch.nr, exirb);
+ hx->bch.nr, exirb);
}
} else if (hx->bch.nr & 2) { /* HSCX B */
if (ista & (HSCX__EXA | HSCX__ICA))
@@ -1093,7 +1103,7 @@ ipac_irq(struct hscx_hw *hx, u8 ista)
if (ista & HSCX__EXB) {
exirb = ReadHSCX(hx, IPAC_EXIRB);
pr_debug("%s: B%1d EXIRB %02x\n", hx->ip->name,
- hx->bch.nr, exirb);
+ hx->bch.nr, exirb);
}
istab = ista & 0xF8;
} else { /* HSCX A */
@@ -1101,7 +1111,7 @@ ipac_irq(struct hscx_hw *hx, u8 ista)
if (ista & HSCX__EXA) {
exirb = ReadHSCX(hx, IPAC_EXIRB);
pr_debug("%s: B%1d EXIRB %02x\n", hx->ip->name,
- hx->bch.nr, exirb);
+ hx->bch.nr, exirb);
}
istab = istab & 0xF8;
}
@@ -1119,11 +1129,8 @@ ipac_irq(struct hscx_hw *hx, u8 ista)
if (istab & IPACX_B_RPF) {
hscx_empty_fifo(hx, hx->fifo_size);
- if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags)) {
- /* receive transparent audio data */
- if (hx->bch.rx_skb)
- recv_Bchannel(&hx->bch, 0);
- }
+ if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags))
+ recv_Bchannel(&hx->bch, 0, false);
}
if (istab & IPACX_B_RFO) {
@@ -1136,11 +1143,13 @@ ipac_irq(struct hscx_hw *hx, u8 ista)
if (istab & IPACX_B_XDU) {
if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags)) {
- hscx_fill_fifo(hx);
+ if (test_bit(FLG_FILLEMPTY, &hx->bch.Flags))
+ test_and_set_bit(FLG_TX_EMPTY, &hx->bch.Flags);
+ hscx_xpr(hx);
return;
}
pr_debug("%s: B%1d XDU error at len %d\n", hx->ip->name,
- hx->bch.nr, hx->bch.tx_idx);
+ hx->bch.nr, hx->bch.tx_idx);
hx->bch.tx_idx = 0;
hscx_cmdr(hx, 0x01); /* XRES */
}
@@ -1203,10 +1212,10 @@ mISDNipac_irq(struct ipac_hw *ipac, int maxloop)
return IRQ_NONE;
if (cnt < maxloop)
pr_debug("%s: %d irqloops cpu%d\n", ipac->name,
- maxloop - cnt, smp_processor_id());
+ maxloop - cnt, smp_processor_id());
if (maxloop && !cnt)
pr_notice("%s: %d IRQ LOOP cpu%d\n", ipac->name,
- maxloop, smp_processor_id());
+ maxloop, smp_processor_id());
return IRQ_HANDLED;
}
EXPORT_SYMBOL(mISDNipac_irq);
@@ -1215,7 +1224,7 @@ static int
hscx_mode(struct hscx_hw *hscx, u32 bprotocol)
{
pr_debug("%s: HSCX %c protocol %x-->%x ch %d\n", hscx->ip->name,
- '@' + hscx->bch.nr, hscx->bch.state, bprotocol, hscx->bch.nr);
+ '@' + hscx->bch.nr, hscx->bch.state, bprotocol, hscx->bch.nr);
if (hscx->ip->type & IPAC_TYPE_IPACX) {
if (hscx->bch.nr & 1) { /* B1 and ICA */
WriteIPAC(hscx->ip, ISACX_BCHA_TSDP_BC1, 0x80);
@@ -1337,22 +1346,17 @@ hscx_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
struct hscx_hw *hx = container_of(bch, struct hscx_hw, bch);
int ret = -EINVAL;
struct mISDNhead *hh = mISDN_HEAD_P(skb);
- u32 id;
- u_long flags;
+ unsigned long flags;
switch (hh->prim) {
case PH_DATA_REQ:
spin_lock_irqsave(hx->ip->hwlock, flags);
ret = bchannel_senddata(bch, skb);
if (ret > 0) { /* direct TX */
- id = hh->id; /* skb can be freed */
ret = 0;
hscx_fill_fifo(hx);
- spin_unlock_irqrestore(hx->ip->hwlock, flags);
- if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
- queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
- } else
- spin_unlock_irqrestore(hx->ip->hwlock, flags);
+ }
+ spin_unlock_irqrestore(hx->ip->hwlock, flags);
return ret;
case PH_ACTIVATE_REQ:
spin_lock_irqsave(hx->ip->hwlock, flags);
@@ -1363,7 +1367,7 @@ hscx_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
spin_unlock_irqrestore(hx->ip->hwlock, flags);
if (!ret)
_queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0,
- NULL, GFP_KERNEL);
+ NULL, GFP_KERNEL);
break;
case PH_DEACTIVATE_REQ:
spin_lock_irqsave(hx->ip->hwlock, flags);
@@ -1371,7 +1375,7 @@ hscx_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
hscx_mode(hx, ISDN_P_NONE);
spin_unlock_irqrestore(hx->ip->hwlock, flags);
_queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0,
- NULL, GFP_KERNEL);
+ NULL, GFP_KERNEL);
ret = 0;
break;
default:
@@ -1387,20 +1391,7 @@ hscx_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
static int
channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
{
- int ret = 0;
-
- switch (cq->op) {
- case MISDN_CTRL_GETOP:
- cq->op = 0;
- break;
- /* Nothing implemented yet */
- case MISDN_CTRL_FILL_EMPTY:
- default:
- pr_info("%s: unknown Op %x\n", __func__, cq->op);
- ret = -EINVAL;
- break;
- }
- return ret;
+ return mISDN_ctrl_bchannel(bch, cq);
}
static int
@@ -1415,15 +1406,11 @@ hscx_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
switch (cmd) {
case CLOSE_CHANNEL:
test_and_clear_bit(FLG_OPEN, &bch->Flags);
- if (test_bit(FLG_ACTIVE, &bch->Flags)) {
- spin_lock_irqsave(hx->ip->hwlock, flags);
- mISDN_freebchannel(bch);
- hscx_mode(hx, ISDN_P_NONE);
- spin_unlock_irqrestore(hx->ip->hwlock, flags);
- } else {
- skb_queue_purge(&bch->rqueue);
- bch->rcount = 0;
- }
+ cancel_work_sync(&bch->workq);
+ spin_lock_irqsave(hx->ip->hwlock, flags);
+ mISDN_clear_bchannel(bch);
+ hscx_mode(hx, ISDN_P_NONE);
+ spin_unlock_irqrestore(hx->ip->hwlock, flags);
ch->protocol = ISDN_P_NONE;
ch->peer = NULL;
module_put(hx->ip->owner);
@@ -1466,7 +1453,7 @@ hscx_init(struct hscx_hw *hx)
pr_debug("%s: HSCX VSTR %02x\n", hx->ip->name, val);
if (hx->bch.debug & DEBUG_HW)
pr_notice("%s: HSCX version %s\n", hx->ip->name,
- HSCXVer[val & 0x0f]);
+ HSCXVer[val & 0x0f]);
} else
WriteHSCX(hx, IPAC_CCR1, 0x82);
WriteHSCX(hx, IPAC_CCR2, 0x30);
@@ -1490,7 +1477,7 @@ ipac_init(struct ipac_hw *ipac)
val = ReadIPAC(ipac, IPAC_CONF);
/* conf is default 0, but can be overwritten by card setup */
pr_debug("%s: IPAC CONF %02x/%02x\n", ipac->name,
- val, ipac->conf);
+ val, ipac->conf);
WriteIPAC(ipac, IPAC_CONF, ipac->conf);
val = ReadIPAC(ipac, IPAC_ID);
if (ipac->hscx[0].bch.debug & DEBUG_HW)
@@ -1505,7 +1492,7 @@ open_bchannel(struct ipac_hw *ipac, struct channel_req *rq)
{
struct bchannel *bch;
- if (rq->adr.channel > 2)
+ if (rq->adr.channel == 0 || rq->adr.channel > 2)
return -EINVAL;
if (rq->protocol == ISDN_P_NONE)
return -EINVAL;
@@ -1525,7 +1512,7 @@ channel_ctrl(struct ipac_hw *ipac, struct mISDN_ctrl_req *cq)
switch (cq->op) {
case MISDN_CTRL_GETOP:
- cq->op = MISDN_CTRL_LOOP;
+ cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_L1_TIMER3;
break;
case MISDN_CTRL_LOOP:
/* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
@@ -1535,6 +1522,9 @@ channel_ctrl(struct ipac_hw *ipac, struct mISDN_ctrl_req *cq)
}
ret = ipac->ctrl(ipac, HW_TESTLOOP, cq->channel);
break;
+ case MISDN_CTRL_L1_TIMER3:
+ ret = ipac->isac.ctrl(&ipac->isac, HW_TIMER3_VALUE, cq->p1);
+ break;
default:
pr_info("%s: unknown CTRL OP %x\n", ipac->name, cq->op);
ret = -EINVAL;
@@ -1568,7 +1558,7 @@ ipac_dctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
break;
case CLOSE_CHANNEL:
pr_debug("%s: dev(%d) close from %p\n", ipac->name,
- dch->dev.id, __builtin_return_address(0));
+ dch->dev.id, __builtin_return_address(0));
module_put(ipac->owner);
break;
case CONTROL_CHANNEL:
@@ -1619,8 +1609,9 @@ mISDNipac_init(struct ipac_hw *ipac, void *hw)
ipac->hscx[i].bch.nr = i + 1;
set_channelmap(i + 1, ipac->isac.dch.dev.channelmap);
list_add(&ipac->hscx[i].bch.ch.list,
- &ipac->isac.dch.dev.bchannels);
- mISDN_initbchannel(&ipac->hscx[i].bch, MAX_DATA_MEM);
+ &ipac->isac.dch.dev.bchannels);
+ mISDN_initbchannel(&ipac->hscx[i].bch, MAX_DATA_MEM,
+ ipac->hscx[i].fifo_size);
ipac->hscx[i].bch.ch.nr = i + 1;
ipac->hscx[i].bch.ch.send = &hscx_l2l1;
ipac->hscx[i].bch.ch.ctrl = hscx_bctrl;