diff options
Diffstat (limited to 'drivers/isdn/hardware/mISDN/mISDNipac.c')
| -rw-r--r-- | drivers/isdn/hardware/mISDN/mISDNipac.c | 255 |
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; |
