diff options
author | Karsten Keil <kkeil@linux-pingi.de> | 2012-05-15 19:51:07 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-05-16 15:24:05 -0400 |
commit | 6d1ee48fd0d8d2586aaeda24dacffc426c2be44a (patch) | |
tree | 0a94204bfdf5ac0eb4d03885cb2f87ddb0e8eb1a /drivers/isdn | |
parent | 034005a0119b9c2aabe0ac3953eb9a65ca937a69 (diff) |
mISDN: Implement MISDN_CTRL_FILL_EMPTY for more drivers
MISDN_CTRL_FILL_EMPTY is a meachanism to send a fixed value (normally silence)
as long no data from upper layers is available. It can be used when recording
voice messages or with unidirectional protocols.
Signed-off-by: Karsten Keil <kkeil@linux-pingi.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/isdn')
-rw-r--r-- | drivers/isdn/hardware/mISDN/avmfritz.c | 64 | ||||
-rw-r--r-- | drivers/isdn/hardware/mISDN/hfcmulti.c | 12 | ||||
-rw-r--r-- | drivers/isdn/hardware/mISDN/hfcpci.c | 59 | ||||
-rw-r--r-- | drivers/isdn/hardware/mISDN/hfcsusb.c | 44 | ||||
-rw-r--r-- | drivers/isdn/hardware/mISDN/mISDNipac.c | 44 | ||||
-rw-r--r-- | drivers/isdn/hardware/mISDN/mISDNisar.c | 33 | ||||
-rw-r--r-- | drivers/isdn/hardware/mISDN/netjet.c | 78 | ||||
-rw-r--r-- | drivers/isdn/hardware/mISDN/w6692.c | 53 | ||||
-rw-r--r-- | drivers/isdn/mISDN/dsp_core.c | 1 | ||||
-rw-r--r-- | drivers/isdn/mISDN/hwchannel.c | 12 |
10 files changed, 240 insertions, 160 deletions
diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c index 7cd3a963ed2e..c6fa505a1d1b 100644 --- a/drivers/isdn/hardware/mISDN/avmfritz.c +++ b/drivers/isdn/hardware/mISDN/avmfritz.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include "ipac.h" | 30 | #include "ipac.h" |
31 | 31 | ||
32 | 32 | ||
33 | #define AVMFRITZ_REV "2.2" | 33 | #define AVMFRITZ_REV "2.3" |
34 | 34 | ||
35 | static int AVM_cnt; | 35 | static int AVM_cnt; |
36 | static int debug; | 36 | static int debug; |
@@ -442,19 +442,26 @@ hdlc_fill_fifo(struct bchannel *bch) | |||
442 | { | 442 | { |
443 | struct fritzcard *fc = bch->hw; | 443 | struct fritzcard *fc = bch->hw; |
444 | struct hdlc_hw *hdlc; | 444 | struct hdlc_hw *hdlc; |
445 | int count, fs, cnt = 0; | 445 | int count, fs, cnt = 0, idx, fillempty = 0; |
446 | u8 *p; | 446 | u8 *p; |
447 | u32 *ptr, val, addr; | 447 | u32 *ptr, val, addr; |
448 | 448 | ||
449 | hdlc = &fc->hdlc[(bch->nr - 1) & 1]; | 449 | idx = (bch->nr - 1) & 1; |
450 | if (!bch->tx_skb) | 450 | hdlc = &fc->hdlc[idx]; |
451 | return; | ||
452 | count = bch->tx_skb->len - bch->tx_idx; | ||
453 | if (count <= 0) | ||
454 | return; | ||
455 | fs = (fc->type == AVM_FRITZ_PCIV2) ? | 451 | fs = (fc->type == AVM_FRITZ_PCIV2) ? |
456 | HDLC_FIFO_SIZE_V2 : HDLC_FIFO_SIZE_V1; | 452 | HDLC_FIFO_SIZE_V2 : HDLC_FIFO_SIZE_V1; |
457 | p = bch->tx_skb->data + bch->tx_idx; | 453 | if (!bch->tx_skb) { |
454 | if (!test_bit(FLG_TX_EMPTY, &bch->Flags)) | ||
455 | return; | ||
456 | count = fs; | ||
457 | p = bch->fill; | ||
458 | fillempty = 1; | ||
459 | } else { | ||
460 | count = bch->tx_skb->len - bch->tx_idx; | ||
461 | if (count <= 0) | ||
462 | return; | ||
463 | p = bch->tx_skb->data + bch->tx_idx; | ||
464 | } | ||
458 | hdlc->ctrl.sr.cmd &= ~HDLC_CMD_XME; | 465 | hdlc->ctrl.sr.cmd &= ~HDLC_CMD_XME; |
459 | if (count > fs) { | 466 | if (count > fs) { |
460 | count = fs; | 467 | count = fs; |
@@ -462,10 +469,14 @@ hdlc_fill_fifo(struct bchannel *bch) | |||
462 | if (test_bit(FLG_HDLC, &bch->Flags)) | 469 | if (test_bit(FLG_HDLC, &bch->Flags)) |
463 | hdlc->ctrl.sr.cmd |= HDLC_CMD_XME; | 470 | hdlc->ctrl.sr.cmd |= HDLC_CMD_XME; |
464 | } | 471 | } |
465 | pr_debug("%s: %s %d/%d/%d", fc->name, __func__, count, | ||
466 | bch->tx_idx, bch->tx_skb->len); | ||
467 | ptr = (u32 *)p; | 472 | ptr = (u32 *)p; |
468 | bch->tx_idx += count; | 473 | if (fillempty) { |
474 | pr_debug("%s.B%d: %d/%d/%d", fc->name, bch->nr, count, | ||
475 | bch->tx_idx, bch->tx_skb->len); | ||
476 | bch->tx_idx += count; | ||
477 | } else { | ||
478 | pr_debug("%s.B%d: fillempty %d\n", fc->name, bch->nr, count); | ||
479 | } | ||
469 | hdlc->ctrl.sr.xml = ((count == fs) ? 0 : count); | 480 | hdlc->ctrl.sr.xml = ((count == fs) ? 0 : count); |
470 | if (fc->type == AVM_FRITZ_PCIV2) { | 481 | if (fc->type == AVM_FRITZ_PCIV2) { |
471 | __write_ctrl_pciv2(fc, hdlc, bch->nr); | 482 | __write_ctrl_pciv2(fc, hdlc, bch->nr); |
@@ -475,13 +486,21 @@ hdlc_fill_fifo(struct bchannel *bch) | |||
475 | __write_ctrl_pci(fc, hdlc, bch->nr); | 486 | __write_ctrl_pci(fc, hdlc, bch->nr); |
476 | addr = fc->addr + CHIP_WINDOW; | 487 | addr = fc->addr + CHIP_WINDOW; |
477 | } | 488 | } |
478 | while (cnt < count) { | 489 | if (fillempty) { |
479 | val = get_unaligned(ptr); | 490 | while (cnt < count) { |
480 | outl(cpu_to_le32(val), addr); | 491 | /* all bytes the same - no worry about endian */ |
481 | ptr++; | 492 | outl(*ptr, addr); |
482 | cnt += 4; | 493 | cnt += 4; |
494 | } | ||
495 | } else { | ||
496 | while (cnt < count) { | ||
497 | val = get_unaligned(ptr); | ||
498 | outl(cpu_to_le32(val), addr); | ||
499 | ptr++; | ||
500 | cnt += 4; | ||
501 | } | ||
483 | } | 502 | } |
484 | if (debug & DEBUG_HW_BFIFO) { | 503 | if ((debug & DEBUG_HW_BFIFO) && !fillempty) { |
485 | snprintf(fc->log, LOG_SIZE, "B%1d-send %s %d ", | 504 | snprintf(fc->log, LOG_SIZE, "B%1d-send %s %d ", |
486 | bch->nr, fc->name, count); | 505 | bch->nr, fc->name, count); |
487 | print_hex_dump_bytes(fc->log, DUMP_PREFIX_OFFSET, p, count); | 506 | print_hex_dump_bytes(fc->log, DUMP_PREFIX_OFFSET, p, count); |
@@ -496,8 +515,12 @@ HDLC_irq_xpr(struct bchannel *bch) | |||
496 | } else { | 515 | } else { |
497 | if (bch->tx_skb) | 516 | if (bch->tx_skb) |
498 | dev_kfree_skb(bch->tx_skb); | 517 | dev_kfree_skb(bch->tx_skb); |
499 | if (get_next_bframe(bch)) | 518 | if (get_next_bframe(bch)) { |
500 | hdlc_fill_fifo(bch); | 519 | hdlc_fill_fifo(bch); |
520 | test_and_clear_bit(FLG_TX_EMPTY, &bch->Flags); | ||
521 | } else if (test_bit(FLG_TX_EMPTY, &bch->Flags)) { | ||
522 | hdlc_fill_fifo(bch); | ||
523 | } | ||
501 | } | 524 | } |
502 | } | 525 | } |
503 | 526 | ||
@@ -561,6 +584,8 @@ handle_tx: | |||
561 | if (bch->tx_skb && bch->tx_skb->len) { | 584 | if (bch->tx_skb && bch->tx_skb->len) { |
562 | if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) | 585 | if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) |
563 | bch->tx_idx = 0; | 586 | bch->tx_idx = 0; |
587 | } else if (test_bit(FLG_FILLEMPTY, &bch->Flags)) { | ||
588 | test_and_set_bit(FLG_TX_EMPTY, &bch->Flags); | ||
564 | } | 589 | } |
565 | hdlc->ctrl.sr.xml = 0; | 590 | hdlc->ctrl.sr.xml = 0; |
566 | hdlc->ctrl.sr.cmd |= HDLC_CMD_XRS; | 591 | hdlc->ctrl.sr.cmd |= HDLC_CMD_XRS; |
@@ -882,7 +907,6 @@ open_bchannel(struct fritzcard *fc, struct channel_req *rq) | |||
882 | bch = &fc->bch[rq->adr.channel - 1]; | 907 | bch = &fc->bch[rq->adr.channel - 1]; |
883 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) | 908 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) |
884 | return -EBUSY; /* b-channel can be only open once */ | 909 | return -EBUSY; /* b-channel can be only open once */ |
885 | test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags); | ||
886 | bch->ch.protocol = rq->protocol; | 910 | bch->ch.protocol = rq->protocol; |
887 | rq->ch = &bch->ch; | 911 | rq->ch = &bch->ch; |
888 | return 0; | 912 | return 0; |
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index 3d4b36d2a31a..db9b04519829 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c | |||
@@ -3576,7 +3576,7 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) | |||
3576 | case MISDN_CTRL_GETOP: | 3576 | case MISDN_CTRL_GETOP: |
3577 | ret = mISDN_ctrl_bchannel(bch, cq); | 3577 | ret = mISDN_ctrl_bchannel(bch, cq); |
3578 | cq->op |= MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP | | 3578 | cq->op |= MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP | |
3579 | MISDN_CTRL_RX_OFF | MISDN_CTRL_FILL_EMPTY; | 3579 | MISDN_CTRL_RX_OFF; |
3580 | break; | 3580 | break; |
3581 | case MISDN_CTRL_RX_OFF: /* turn off / on rx stream */ | 3581 | case MISDN_CTRL_RX_OFF: /* turn off / on rx stream */ |
3582 | hc->chan[bch->slot].rx_off = !!cq->p1; | 3582 | hc->chan[bch->slot].rx_off = !!cq->p1; |
@@ -3591,11 +3591,10 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) | |||
3591 | printk(KERN_DEBUG "%s: RX_OFF request (nr=%d off=%d)\n", | 3591 | printk(KERN_DEBUG "%s: RX_OFF request (nr=%d off=%d)\n", |
3592 | __func__, bch->nr, hc->chan[bch->slot].rx_off); | 3592 | __func__, bch->nr, hc->chan[bch->slot].rx_off); |
3593 | break; | 3593 | break; |
3594 | case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */ | 3594 | case MISDN_CTRL_FILL_EMPTY: |
3595 | test_and_set_bit(FLG_FILLEMPTY, &bch->Flags); | 3595 | ret = mISDN_ctrl_bchannel(bch, cq); |
3596 | if (debug & DEBUG_HFCMULTI_MSG) | 3596 | hc->silence = bch->fill[0]; |
3597 | printk(KERN_DEBUG "%s: FILL_EMPTY request (nr=%d " | 3597 | memset(hc->silence_data, hc->silence, sizeof(hc->silence_data)); |
3598 | "off=%d)\n", __func__, bch->nr, !!cq->p1); | ||
3599 | break; | 3598 | break; |
3600 | case MISDN_CTRL_HW_FEATURES: /* fill features structure */ | 3599 | case MISDN_CTRL_HW_FEATURES: /* fill features structure */ |
3601 | if (debug & DEBUG_HFCMULTI_MSG) | 3600 | if (debug & DEBUG_HFCMULTI_MSG) |
@@ -4118,7 +4117,6 @@ open_bchannel(struct hfc_multi *hc, struct dchannel *dch, | |||
4118 | } | 4117 | } |
4119 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) | 4118 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) |
4120 | return -EBUSY; /* b-channel can be only open once */ | 4119 | return -EBUSY; /* b-channel can be only open once */ |
4121 | test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags); | ||
4122 | bch->ch.protocol = rq->protocol; | 4120 | bch->ch.protocol = rq->protocol; |
4123 | hc->chan[ch].rx_off = 0; | 4121 | hc->chan[ch].rx_off = 0; |
4124 | rq->ch = &bch->ch; | 4122 | rq->ch = &bch->ch; |
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c index 27743754ab81..1bd8bc7eb5c7 100644 --- a/drivers/isdn/hardware/mISDN/hfcpci.c +++ b/drivers/isdn/hardware/mISDN/hfcpci.c | |||
@@ -565,11 +565,6 @@ hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *rxbz, | |||
565 | if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL)) | 565 | if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL)) |
566 | new_z2 -= B_FIFO_SIZE; /* buffer wrap */ | 566 | new_z2 -= B_FIFO_SIZE; /* buffer wrap */ |
567 | 567 | ||
568 | if (fcnt_rx > MAX_DATA_SIZE) { /* flush, if oversized */ | ||
569 | *z2r = cpu_to_le16(new_z2); /* new position */ | ||
570 | return; | ||
571 | } | ||
572 | |||
573 | fcnt_tx = le16_to_cpu(*z2t) - le16_to_cpu(*z1t); | 568 | fcnt_tx = le16_to_cpu(*z2t) - le16_to_cpu(*z1t); |
574 | if (fcnt_tx <= 0) | 569 | if (fcnt_tx <= 0) |
575 | fcnt_tx += B_FIFO_SIZE; | 570 | fcnt_tx += B_FIFO_SIZE; |
@@ -761,9 +756,14 @@ hfcpci_fill_fifo(struct bchannel *bch) | |||
761 | 756 | ||
762 | if ((bch->debug & DEBUG_HW_BCHANNEL) && !(bch->debug & DEBUG_HW_BFIFO)) | 757 | if ((bch->debug & DEBUG_HW_BCHANNEL) && !(bch->debug & DEBUG_HW_BFIFO)) |
763 | printk(KERN_DEBUG "%s\n", __func__); | 758 | printk(KERN_DEBUG "%s\n", __func__); |
764 | if ((!bch->tx_skb) || bch->tx_skb->len <= 0) | 759 | if ((!bch->tx_skb) || bch->tx_skb->len == 0) { |
765 | return; | 760 | if (!test_bit(FLG_FILLEMPTY, &bch->Flags) && |
766 | count = bch->tx_skb->len - bch->tx_idx; | 761 | !test_bit(FLG_TRANSPARENT, &bch->Flags)) |
762 | return; | ||
763 | count = HFCPCI_FILLEMPTY; | ||
764 | } else { | ||
765 | count = bch->tx_skb->len - bch->tx_idx; | ||
766 | } | ||
767 | if ((bch->nr & 2) && (!hc->hw.bswapped)) { | 767 | if ((bch->nr & 2) && (!hc->hw.bswapped)) { |
768 | bz = &((union fifo_area *)(hc->hw.fifos))->b_chans.txbz_b2; | 768 | bz = &((union fifo_area *)(hc->hw.fifos))->b_chans.txbz_b2; |
769 | bdata = ((union fifo_area *)(hc->hw.fifos))->b_chans.txdat_b2; | 769 | bdata = ((union fifo_area *)(hc->hw.fifos))->b_chans.txdat_b2; |
@@ -782,16 +782,10 @@ hfcpci_fill_fifo(struct bchannel *bch) | |||
782 | fcnt = le16_to_cpu(*z2t) - le16_to_cpu(*z1t); | 782 | fcnt = le16_to_cpu(*z2t) - le16_to_cpu(*z1t); |
783 | if (fcnt <= 0) | 783 | if (fcnt <= 0) |
784 | fcnt += B_FIFO_SIZE; | 784 | fcnt += B_FIFO_SIZE; |
785 | /* fcnt contains available bytes in fifo */ | 785 | if (test_bit(FLG_FILLEMPTY, &bch->Flags)) { |
786 | fcnt = B_FIFO_SIZE - fcnt; | 786 | /* fcnt contains available bytes in fifo */ |
787 | /* remaining bytes to send (bytes in fifo) */ | 787 | if (count > fcnt) |
788 | 788 | count = fcnt; | |
789 | /* "fill fifo if empty" feature */ | ||
790 | if (test_bit(FLG_FILLEMPTY, &bch->Flags) && !fcnt) { | ||
791 | /* printk(KERN_DEBUG "%s: buffer empty, so we have " | ||
792 | "underrun\n", __func__); */ | ||
793 | /* fill buffer, to prevent future underrun */ | ||
794 | count = HFCPCI_FILLEMPTY; | ||
795 | new_z1 = le16_to_cpu(*z1t) + count; | 789 | new_z1 = le16_to_cpu(*z1t) + count; |
796 | /* new buffer Position */ | 790 | /* new buffer Position */ |
797 | if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL)) | 791 | if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL)) |
@@ -803,17 +797,20 @@ hfcpci_fill_fifo(struct bchannel *bch) | |||
803 | printk(KERN_DEBUG "hfcpci_FFt fillempty " | 797 | printk(KERN_DEBUG "hfcpci_FFt fillempty " |
804 | "fcnt(%d) maxl(%d) nz1(%x) dst(%p)\n", | 798 | "fcnt(%d) maxl(%d) nz1(%x) dst(%p)\n", |
805 | fcnt, maxlen, new_z1, dst); | 799 | fcnt, maxlen, new_z1, dst); |
806 | fcnt += count; | ||
807 | if (maxlen > count) | 800 | if (maxlen > count) |
808 | maxlen = count; /* limit size */ | 801 | maxlen = count; /* limit size */ |
809 | memset(dst, 0x2a, maxlen); /* first copy */ | 802 | memset(dst, bch->fill[0], maxlen); /* first copy */ |
810 | count -= maxlen; /* remaining bytes */ | 803 | count -= maxlen; /* remaining bytes */ |
811 | if (count) { | 804 | if (count) { |
812 | dst = bdata; /* start of buffer */ | 805 | dst = bdata; /* start of buffer */ |
813 | memset(dst, 0x2a, count); | 806 | memset(dst, bch->fill[0], count); |
814 | } | 807 | } |
815 | *z1t = cpu_to_le16(new_z1); /* now send data */ | 808 | *z1t = cpu_to_le16(new_z1); /* now send data */ |
809 | return; | ||
816 | } | 810 | } |
811 | /* fcnt contains available bytes in fifo */ | ||
812 | fcnt = B_FIFO_SIZE - fcnt; | ||
813 | /* remaining bytes to send (bytes in fifo) */ | ||
817 | 814 | ||
818 | next_t_frame: | 815 | next_t_frame: |
819 | count = bch->tx_skb->len - bch->tx_idx; | 816 | count = bch->tx_skb->len - bch->tx_idx; |
@@ -1531,24 +1528,7 @@ deactivate_bchannel(struct bchannel *bch) | |||
1531 | static int | 1528 | static int |
1532 | channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) | 1529 | channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) |
1533 | { | 1530 | { |
1534 | int ret = 0; | 1531 | return mISDN_ctrl_bchannel(bch, cq); |
1535 | |||
1536 | switch (cq->op) { | ||
1537 | case MISDN_CTRL_GETOP: | ||
1538 | ret = mISDN_ctrl_bchannel(bch, cq); | ||
1539 | cq->op |= MISDN_CTRL_FILL_EMPTY; | ||
1540 | break; | ||
1541 | case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */ | ||
1542 | test_and_set_bit(FLG_FILLEMPTY, &bch->Flags); | ||
1543 | if (debug & DEBUG_HW_OPEN) | ||
1544 | printk(KERN_DEBUG "%s: FILL_EMPTY request (nr=%d " | ||
1545 | "off=%d)\n", __func__, bch->nr, !!cq->p1); | ||
1546 | break; | ||
1547 | default: | ||
1548 | ret = mISDN_ctrl_bchannel(bch, cq); | ||
1549 | break; | ||
1550 | } | ||
1551 | return ret; | ||
1552 | } | 1532 | } |
1553 | static int | 1533 | static int |
1554 | hfc_bctrl(struct mISDNchannel *ch, u_int cmd, void *arg) | 1534 | hfc_bctrl(struct mISDNchannel *ch, u_int cmd, void *arg) |
@@ -1964,7 +1944,6 @@ open_bchannel(struct hfc_pci *hc, struct channel_req *rq) | |||
1964 | bch = &hc->bch[rq->adr.channel - 1]; | 1944 | bch = &hc->bch[rq->adr.channel - 1]; |
1965 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) | 1945 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) |
1966 | return -EBUSY; /* b-channel can be only open once */ | 1946 | return -EBUSY; /* b-channel can be only open once */ |
1967 | test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags); | ||
1968 | bch->ch.protocol = rq->protocol; | 1947 | bch->ch.protocol = rq->protocol; |
1969 | rq->ch = &bch->ch; /* TODO: E-channel */ | 1948 | rq->ch = &bch->ch; /* TODO: E-channel */ |
1970 | if (!try_module_get(THIS_MODULE)) | 1949 | if (!try_module_get(THIS_MODULE)) |
diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c index 9c17473da83b..b539b10d6f3e 100644 --- a/drivers/isdn/hardware/mISDN/hfcsusb.c +++ b/drivers/isdn/hardware/mISDN/hfcsusb.c | |||
@@ -491,7 +491,6 @@ open_bchannel(struct hfcsusb *hw, struct channel_req *rq) | |||
491 | bch = &hw->bch[rq->adr.channel - 1]; | 491 | bch = &hw->bch[rq->adr.channel - 1]; |
492 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) | 492 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) |
493 | return -EBUSY; /* b-channel can be only open once */ | 493 | return -EBUSY; /* b-channel can be only open once */ |
494 | test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags); | ||
495 | bch->ch.protocol = rq->protocol; | 494 | bch->ch.protocol = rq->protocol; |
496 | rq->ch = &bch->ch; | 495 | rq->ch = &bch->ch; |
497 | 496 | ||
@@ -806,24 +805,7 @@ hfcsusb_ph_command(struct hfcsusb *hw, u_char command) | |||
806 | static int | 805 | static int |
807 | channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) | 806 | channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) |
808 | { | 807 | { |
809 | int ret = 0; | 808 | return mISDN_ctrl_bchannel(bch, cq); |
810 | |||
811 | switch (cq->op) { | ||
812 | case MISDN_CTRL_GETOP: | ||
813 | ret = mISDN_ctrl_bchannel(bch, cq); | ||
814 | cq->op |= MISDN_CTRL_FILL_EMPTY; | ||
815 | break; | ||
816 | case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */ | ||
817 | test_and_set_bit(FLG_FILLEMPTY, &bch->Flags); | ||
818 | if (debug & DEBUG_HW_OPEN) | ||
819 | printk(KERN_DEBUG "%s: FILL_EMPTY request (nr=%d " | ||
820 | "off=%d)\n", __func__, bch->nr, !!cq->p1); | ||
821 | break; | ||
822 | default: | ||
823 | ret = mISDN_ctrl_bchannel(bch, cq); | ||
824 | break; | ||
825 | } | ||
826 | return ret; | ||
827 | } | 809 | } |
828 | 810 | ||
829 | /* collect data from incoming interrupt or isochron USB data */ | 811 | /* collect data from incoming interrupt or isochron USB data */ |
@@ -1183,8 +1165,8 @@ tx_iso_complete(struct urb *urb) | |||
1183 | int k, tx_offset, num_isoc_packets, sink, remain, current_len, | 1165 | int k, tx_offset, num_isoc_packets, sink, remain, current_len, |
1184 | errcode, hdlc, i; | 1166 | errcode, hdlc, i; |
1185 | int *tx_idx; | 1167 | int *tx_idx; |
1186 | int frame_complete, fifon, status; | 1168 | int frame_complete, fifon, status, fillempty = 0; |
1187 | __u8 threshbit; | 1169 | __u8 threshbit, *p; |
1188 | 1170 | ||
1189 | spin_lock(&hw->lock); | 1171 | spin_lock(&hw->lock); |
1190 | if (fifo->stop_gracefull) { | 1172 | if (fifo->stop_gracefull) { |
@@ -1202,6 +1184,9 @@ tx_iso_complete(struct urb *urb) | |||
1202 | tx_skb = fifo->bch->tx_skb; | 1184 | tx_skb = fifo->bch->tx_skb; |
1203 | tx_idx = &fifo->bch->tx_idx; | 1185 | tx_idx = &fifo->bch->tx_idx; |
1204 | hdlc = test_bit(FLG_HDLC, &fifo->bch->Flags); | 1186 | hdlc = test_bit(FLG_HDLC, &fifo->bch->Flags); |
1187 | if (!tx_skb && !hdlc && | ||
1188 | test_bit(FLG_FILLEMPTY, &fifo->bch->Flags)) | ||
1189 | fillempty = 1; | ||
1205 | } else { | 1190 | } else { |
1206 | printk(KERN_DEBUG "%s: %s: neither BCH nor DCH\n", | 1191 | printk(KERN_DEBUG "%s: %s: neither BCH nor DCH\n", |
1207 | hw->name, __func__); | 1192 | hw->name, __func__); |
@@ -1260,6 +1245,8 @@ tx_iso_complete(struct urb *urb) | |||
1260 | /* Generate next ISO Packets */ | 1245 | /* Generate next ISO Packets */ |
1261 | if (tx_skb) | 1246 | if (tx_skb) |
1262 | remain = tx_skb->len - *tx_idx; | 1247 | remain = tx_skb->len - *tx_idx; |
1248 | else if (fillempty) | ||
1249 | remain = 15; /* > not complete */ | ||
1263 | else | 1250 | else |
1264 | remain = 0; | 1251 | remain = 0; |
1265 | 1252 | ||
@@ -1290,15 +1277,20 @@ tx_iso_complete(struct urb *urb) | |||
1290 | } | 1277 | } |
1291 | 1278 | ||
1292 | /* copy tx data to iso-urb buffer */ | 1279 | /* copy tx data to iso-urb buffer */ |
1293 | memcpy(context_iso_urb->buffer + tx_offset + 1, | 1280 | p = context_iso_urb->buffer + tx_offset + 1; |
1294 | (tx_skb->data + *tx_idx), current_len); | 1281 | if (fillempty) { |
1295 | *tx_idx += current_len; | 1282 | memset(p, fifo->bch->fill[0], |
1296 | 1283 | current_len); | |
1284 | } else { | ||
1285 | memcpy(p, (tx_skb->data + *tx_idx), | ||
1286 | current_len); | ||
1287 | *tx_idx += current_len; | ||
1288 | } | ||
1297 | urb->iso_frame_desc[k].offset = tx_offset; | 1289 | urb->iso_frame_desc[k].offset = tx_offset; |
1298 | urb->iso_frame_desc[k].length = current_len + 1; | 1290 | urb->iso_frame_desc[k].length = current_len + 1; |
1299 | 1291 | ||
1300 | /* USB data log for every D ISO out */ | 1292 | /* USB data log for every D ISO out */ |
1301 | if ((fifon == HFCUSB_D_RX) && | 1293 | if ((fifon == HFCUSB_D_RX) && !fillempty && |
1302 | (debug & DBG_HFC_USB_VERBOSE)) { | 1294 | (debug & DBG_HFC_USB_VERBOSE)) { |
1303 | printk(KERN_DEBUG | 1295 | printk(KERN_DEBUG |
1304 | "%s: %s (%d/%d) offs(%d) len(%d) ", | 1296 | "%s: %s (%d/%d) offs(%d) len(%d) ", |
diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c index 3e71a5ef4bbc..374a17751ffb 100644 --- a/drivers/isdn/hardware/mISDN/mISDNipac.c +++ b/drivers/isdn/hardware/mISDN/mISDNipac.c | |||
@@ -969,22 +969,28 @@ hscx_fill_fifo(struct hscx_hw *hscx) | |||
969 | int count, more; | 969 | int count, more; |
970 | u8 *p; | 970 | u8 *p; |
971 | 971 | ||
972 | if (!hscx->bch.tx_skb) | 972 | if (!hscx->bch.tx_skb) { |
973 | return; | 973 | if (!test_bit(FLG_TX_EMPTY, &hscx->bch.Flags)) |
974 | count = hscx->bch.tx_skb->len - hscx->bch.tx_idx; | 974 | return; |
975 | if (count <= 0) | ||
976 | return; | ||
977 | p = hscx->bch.tx_skb->data + hscx->bch.tx_idx; | ||
978 | |||
979 | more = test_bit(FLG_TRANSPARENT, &hscx->bch.Flags) ? 1 : 0; | ||
980 | if (count > hscx->fifo_size) { | ||
981 | count = hscx->fifo_size; | 975 | count = hscx->fifo_size; |
982 | more = 1; | 976 | more = 1; |
983 | } | 977 | p = hscx->log; |
984 | pr_debug("%s: B%1d %d/%d/%d\n", hscx->ip->name, hscx->bch.nr, count, | 978 | memset(p, hscx->bch.fill[0], count); |
985 | hscx->bch.tx_idx, hscx->bch.tx_skb->len); | 979 | } else { |
986 | hscx->bch.tx_idx += count; | 980 | count = hscx->bch.tx_skb->len - hscx->bch.tx_idx; |
981 | if (count <= 0) | ||
982 | return; | ||
983 | p = hscx->bch.tx_skb->data + hscx->bch.tx_idx; | ||
987 | 984 | ||
985 | more = test_bit(FLG_TRANSPARENT, &hscx->bch.Flags) ? 1 : 0; | ||
986 | if (count > hscx->fifo_size) { | ||
987 | count = hscx->fifo_size; | ||
988 | more = 1; | ||
989 | } | ||
990 | pr_debug("%s: B%1d %d/%d/%d\n", hscx->ip->name, hscx->bch.nr, | ||
991 | count, hscx->bch.tx_idx, hscx->bch.tx_skb->len); | ||
992 | hscx->bch.tx_idx += count; | ||
993 | } | ||
988 | if (hscx->ip->type & IPAC_TYPE_IPACX) | 994 | if (hscx->ip->type & IPAC_TYPE_IPACX) |
989 | hscx->ip->write_fifo(hscx->ip->hw, | 995 | hscx->ip->write_fifo(hscx->ip->hw, |
990 | hscx->off + IPACX_XFIFOB, p, count); | 996 | hscx->off + IPACX_XFIFOB, p, count); |
@@ -995,7 +1001,7 @@ hscx_fill_fifo(struct hscx_hw *hscx) | |||
995 | } | 1001 | } |
996 | hscx_cmdr(hscx, more ? 0x08 : 0x0a); | 1002 | hscx_cmdr(hscx, more ? 0x08 : 0x0a); |
997 | 1003 | ||
998 | if (hscx->bch.debug & DEBUG_HW_BFIFO) { | 1004 | if (hscx->bch.tx_skb && (hscx->bch.debug & DEBUG_HW_BFIFO)) { |
999 | snprintf(hscx->log, 64, "B%1d-send %s %d ", | 1005 | snprintf(hscx->log, 64, "B%1d-send %s %d ", |
1000 | hscx->bch.nr, hscx->ip->name, count); | 1006 | hscx->bch.nr, hscx->ip->name, count); |
1001 | print_hex_dump_bytes(hscx->log, DUMP_PREFIX_OFFSET, p, count); | 1007 | print_hex_dump_bytes(hscx->log, DUMP_PREFIX_OFFSET, p, count); |
@@ -1010,8 +1016,12 @@ hscx_xpr(struct hscx_hw *hx) | |||
1010 | } else { | 1016 | } else { |
1011 | if (hx->bch.tx_skb) | 1017 | if (hx->bch.tx_skb) |
1012 | dev_kfree_skb(hx->bch.tx_skb); | 1018 | dev_kfree_skb(hx->bch.tx_skb); |
1013 | if (get_next_bframe(&hx->bch)) | 1019 | if (get_next_bframe(&hx->bch)) { |
1014 | hscx_fill_fifo(hx); | 1020 | hscx_fill_fifo(hx); |
1021 | test_and_clear_bit(FLG_TX_EMPTY, &hx->bch.Flags); | ||
1022 | } else if (test_bit(FLG_TX_EMPTY, &hx->bch.Flags)) { | ||
1023 | hscx_fill_fifo(hx); | ||
1024 | } | ||
1015 | } | 1025 | } |
1016 | } | 1026 | } |
1017 | 1027 | ||
@@ -1128,7 +1138,9 @@ ipac_irq(struct hscx_hw *hx, u8 ista) | |||
1128 | 1138 | ||
1129 | if (istab & IPACX_B_XDU) { | 1139 | if (istab & IPACX_B_XDU) { |
1130 | if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags)) { | 1140 | if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags)) { |
1131 | hscx_fill_fifo(hx); | 1141 | if (test_bit(FLG_FILLEMPTY, &hx->bch.Flags)) |
1142 | test_and_set_bit(FLG_TX_EMPTY, &hx->bch.Flags); | ||
1143 | hscx_xpr(hx); | ||
1132 | return; | 1144 | return; |
1133 | } | 1145 | } |
1134 | pr_debug("%s: B%1d XDU error at len %d\n", hx->ip->name, | 1146 | pr_debug("%s: B%1d XDU error at len %d\n", hx->ip->name, |
diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c index e74ad385e73f..901be3257a7b 100644 --- a/drivers/isdn/hardware/mISDN/mISDNisar.c +++ b/drivers/isdn/hardware/mISDN/mISDNisar.c | |||
@@ -585,16 +585,25 @@ isar_fill_fifo(struct isar_ch *ch) | |||
585 | u8 msb; | 585 | u8 msb; |
586 | u8 *ptr; | 586 | u8 *ptr; |
587 | 587 | ||
588 | pr_debug("%s: ch%d tx_skb %p tx_idx %d\n", | 588 | pr_debug("%s: ch%d tx_skb %d tx_idx %d\n", ch->is->name, ch->bch.nr, |
589 | ch->is->name, ch->bch.nr, ch->bch.tx_skb, ch->bch.tx_idx); | 589 | ch->bch.tx_skb ? ch->bch.tx_skb->len : -1, ch->bch.tx_idx); |
590 | if (!ch->bch.tx_skb) | 590 | if (!(ch->is->bstat & |
591 | (ch->dpath == 1 ? BSTAT_RDM1 : BSTAT_RDM2))) | ||
592 | return; | ||
593 | if (!ch->bch.tx_skb) { | ||
594 | if (!test_bit(FLG_TX_EMPTY, &ch->bch.Flags) || | ||
595 | (ch->bch.state != ISDN_P_B_RAW)) | ||
596 | return; | ||
597 | count = ch->mml; | ||
598 | /* use the card buffer */ | ||
599 | memset(ch->is->buf, ch->bch.fill[0], count); | ||
600 | send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA, | ||
601 | 0, count, ch->is->buf); | ||
591 | return; | 602 | return; |
603 | } | ||
592 | count = ch->bch.tx_skb->len - ch->bch.tx_idx; | 604 | count = ch->bch.tx_skb->len - ch->bch.tx_idx; |
593 | if (count <= 0) | 605 | if (count <= 0) |
594 | return; | 606 | return; |
595 | if (!(ch->is->bstat & | ||
596 | (ch->dpath == 1 ? BSTAT_RDM1 : BSTAT_RDM2))) | ||
597 | return; | ||
598 | if (count > ch->mml) { | 607 | if (count > ch->mml) { |
599 | msb = 0; | 608 | msb = 0; |
600 | count = ch->mml; | 609 | count = ch->mml; |
@@ -673,9 +682,9 @@ sel_bch_isar(struct isar_hw *isar, u8 dpath) | |||
673 | static void | 682 | static void |
674 | send_next(struct isar_ch *ch) | 683 | send_next(struct isar_ch *ch) |
675 | { | 684 | { |
676 | pr_debug("%s: %s ch%d tx_skb %p tx_idx %d\n", | 685 | pr_debug("%s: %s ch%d tx_skb %d tx_idx %d\n", ch->is->name, __func__, |
677 | ch->is->name, __func__, ch->bch.nr, | 686 | ch->bch.nr, ch->bch.tx_skb ? ch->bch.tx_skb->len : -1, |
678 | ch->bch.tx_skb, ch->bch.tx_idx); | 687 | ch->bch.tx_idx); |
679 | if (ch->bch.state == ISDN_P_B_T30_FAX) { | 688 | if (ch->bch.state == ISDN_P_B_T30_FAX) { |
680 | if (ch->cmd == PCTRL_CMD_FTH) { | 689 | if (ch->cmd == PCTRL_CMD_FTH) { |
681 | if (test_bit(FLG_LASTDATA, &ch->bch.Flags)) { | 690 | if (test_bit(FLG_LASTDATA, &ch->bch.Flags)) { |
@@ -693,6 +702,9 @@ send_next(struct isar_ch *ch) | |||
693 | dev_kfree_skb(ch->bch.tx_skb); | 702 | dev_kfree_skb(ch->bch.tx_skb); |
694 | if (get_next_bframe(&ch->bch)) { | 703 | if (get_next_bframe(&ch->bch)) { |
695 | isar_fill_fifo(ch); | 704 | isar_fill_fifo(ch); |
705 | test_and_clear_bit(FLG_TX_EMPTY, &ch->bch.Flags); | ||
706 | } else if (test_bit(FLG_TX_EMPTY, &ch->bch.Flags)) { | ||
707 | isar_fill_fifo(ch); | ||
696 | } else { | 708 | } else { |
697 | if (test_and_clear_bit(FLG_DLEETX, &ch->bch.Flags)) { | 709 | if (test_and_clear_bit(FLG_DLEETX, &ch->bch.Flags)) { |
698 | if (test_and_clear_bit(FLG_LASTDATA, | 710 | if (test_and_clear_bit(FLG_LASTDATA, |
@@ -707,6 +719,8 @@ send_next(struct isar_ch *ch) | |||
707 | } else { | 719 | } else { |
708 | deliver_status(ch, HW_MOD_CONNECT); | 720 | deliver_status(ch, HW_MOD_CONNECT); |
709 | } | 721 | } |
722 | } else if (test_bit(FLG_FILLEMPTY, &ch->bch.Flags)) { | ||
723 | test_and_set_bit(FLG_TX_EMPTY, &ch->bch.Flags); | ||
710 | } | 724 | } |
711 | } | 725 | } |
712 | } | 726 | } |
@@ -1638,7 +1652,6 @@ isar_open(struct isar_hw *isar, struct channel_req *rq) | |||
1638 | bch = &isar->ch[rq->adr.channel - 1].bch; | 1652 | bch = &isar->ch[rq->adr.channel - 1].bch; |
1639 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) | 1653 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) |
1640 | return -EBUSY; /* b-channel can be only open once */ | 1654 | return -EBUSY; /* b-channel can be only open once */ |
1641 | test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags); | ||
1642 | bch->ch.protocol = rq->protocol; | 1655 | bch->ch.protocol = rq->protocol; |
1643 | rq->ch = &bch->ch; | 1656 | rq->ch = &bch->ch; |
1644 | return 0; | 1657 | return 0; |
diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c index 47d30749d8a7..aa95cc7d32f9 100644 --- a/drivers/isdn/hardware/mISDN/netjet.c +++ b/drivers/isdn/hardware/mISDN/netjet.c | |||
@@ -533,22 +533,31 @@ static void | |||
533 | fill_dma(struct tiger_ch *bc) | 533 | fill_dma(struct tiger_ch *bc) |
534 | { | 534 | { |
535 | struct tiger_hw *card = bc->bch.hw; | 535 | struct tiger_hw *card = bc->bch.hw; |
536 | int count, i; | 536 | int count, i, fillempty = 0; |
537 | u32 m, v; | 537 | u32 m, v, n = 0; |
538 | u8 *p; | 538 | u8 *p; |
539 | 539 | ||
540 | if (bc->free == 0) | 540 | if (bc->free == 0) |
541 | return; | 541 | return; |
542 | count = bc->bch.tx_skb->len - bc->bch.tx_idx; | 542 | if (!bc->bch.tx_skb) { |
543 | if (count <= 0) | 543 | if (!test_bit(FLG_TX_EMPTY, &bc->bch.Flags)) |
544 | return; | 544 | return; |
545 | pr_debug("%s: %s B%1d %d/%d/%d/%d state %x idx %d/%d\n", card->name, | 545 | fillempty = 1; |
546 | __func__, bc->bch.nr, count, bc->free, bc->bch.tx_idx, | 546 | count = card->send.size >> 1; |
547 | bc->bch.tx_skb->len, bc->txstate, bc->idx, card->send.idx); | 547 | p = bc->bch.fill; |
548 | } else { | ||
549 | count = bc->bch.tx_skb->len - bc->bch.tx_idx; | ||
550 | if (count <= 0) | ||
551 | return; | ||
552 | pr_debug("%s: %s B%1d %d/%d/%d/%d state %x idx %d/%d\n", | ||
553 | card->name, __func__, bc->bch.nr, count, bc->free, | ||
554 | bc->bch.tx_idx, bc->bch.tx_skb->len, bc->txstate, | ||
555 | bc->idx, card->send.idx); | ||
556 | p = bc->bch.tx_skb->data + bc->bch.tx_idx; | ||
557 | } | ||
548 | if (bc->txstate & (TX_IDLE | TX_INIT | TX_UNDERRUN)) | 558 | if (bc->txstate & (TX_IDLE | TX_INIT | TX_UNDERRUN)) |
549 | resync(bc, card); | 559 | resync(bc, card); |
550 | p = bc->bch.tx_skb->data + bc->bch.tx_idx; | 560 | if (test_bit(FLG_HDLC, &bc->bch.Flags) && !fillempty) { |
551 | if (test_bit(FLG_HDLC, &bc->bch.Flags)) { | ||
552 | count = isdnhdlc_encode(&bc->hsend, p, count, &i, | 561 | count = isdnhdlc_encode(&bc->hsend, p, count, &i, |
553 | bc->hsbuf, bc->free); | 562 | bc->hsbuf, bc->free); |
554 | pr_debug("%s: B%1d hdlc encoded %d in %d\n", card->name, | 563 | pr_debug("%s: B%1d hdlc encoded %d in %d\n", card->name, |
@@ -559,17 +568,33 @@ fill_dma(struct tiger_ch *bc) | |||
559 | } else { | 568 | } else { |
560 | if (count > bc->free) | 569 | if (count > bc->free) |
561 | count = bc->free; | 570 | count = bc->free; |
562 | bc->bch.tx_idx += count; | 571 | if (!fillempty) |
572 | bc->bch.tx_idx += count; | ||
563 | bc->free -= count; | 573 | bc->free -= count; |
564 | } | 574 | } |
565 | m = (bc->bch.nr & 1) ? 0xffffff00 : 0xffff00ff; | 575 | m = (bc->bch.nr & 1) ? 0xffffff00 : 0xffff00ff; |
566 | for (i = 0; i < count; i++) { | 576 | if (fillempty) { |
567 | if (bc->idx >= card->send.size) | 577 | n = p[0]; |
568 | bc->idx = 0; | 578 | if (!(bc->bch.nr & 1)) |
569 | v = card->send.start[bc->idx]; | 579 | n <<= 8; |
570 | v &= m; | 580 | for (i = 0; i < count; i++) { |
571 | v |= (bc->bch.nr & 1) ? (u32)(p[i]) : ((u32)(p[i])) << 8; | 581 | if (bc->idx >= card->send.size) |
572 | card->send.start[bc->idx++] = v; | 582 | bc->idx = 0; |
583 | v = card->send.start[bc->idx]; | ||
584 | v &= m; | ||
585 | v |= n; | ||
586 | card->send.start[bc->idx++] = v; | ||
587 | } | ||
588 | } else { | ||
589 | for (i = 0; i < count; i++) { | ||
590 | if (bc->idx >= card->send.size) | ||
591 | bc->idx = 0; | ||
592 | v = card->send.start[bc->idx]; | ||
593 | v &= m; | ||
594 | n = p[i]; | ||
595 | v |= (bc->bch.nr & 1) ? n : n << 8; | ||
596 | card->send.start[bc->idx++] = v; | ||
597 | } | ||
573 | } | 598 | } |
574 | if (debug & DEBUG_HW_BFIFO) { | 599 | if (debug & DEBUG_HW_BFIFO) { |
575 | snprintf(card->log, LOG_SIZE, "B%1d-send %s %d ", | 600 | snprintf(card->log, LOG_SIZE, "B%1d-send %s %d ", |
@@ -584,17 +609,26 @@ fill_dma(struct tiger_ch *bc) | |||
584 | static int | 609 | static int |
585 | bc_next_frame(struct tiger_ch *bc) | 610 | bc_next_frame(struct tiger_ch *bc) |
586 | { | 611 | { |
612 | int ret = 1; | ||
613 | |||
587 | if (bc->bch.tx_skb && bc->bch.tx_idx < bc->bch.tx_skb->len) { | 614 | if (bc->bch.tx_skb && bc->bch.tx_idx < bc->bch.tx_skb->len) { |
588 | fill_dma(bc); | 615 | fill_dma(bc); |
589 | } else { | 616 | } else { |
590 | if (bc->bch.tx_skb) | 617 | if (bc->bch.tx_skb) |
591 | dev_kfree_skb(bc->bch.tx_skb); | 618 | dev_kfree_skb(bc->bch.tx_skb); |
592 | if (get_next_bframe(&bc->bch)) | 619 | if (get_next_bframe(&bc->bch)) { |
593 | fill_dma(bc); | 620 | fill_dma(bc); |
594 | else | 621 | test_and_clear_bit(FLG_TX_EMPTY, &bc->bch.Flags); |
595 | return 0; | 622 | } else if (test_bit(FLG_TX_EMPTY, &bc->bch.Flags)) { |
623 | fill_dma(bc); | ||
624 | } else if (test_bit(FLG_FILLEMPTY, &bc->bch.Flags)) { | ||
625 | test_and_set_bit(FLG_TX_EMPTY, &bc->bch.Flags); | ||
626 | ret = 0; | ||
627 | } else { | ||
628 | ret = 0; | ||
629 | } | ||
596 | } | 630 | } |
597 | return 1; | 631 | return ret; |
598 | } | 632 | } |
599 | 633 | ||
600 | static void | 634 | static void |
diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c index 03fb4a34fd53..183181f01927 100644 --- a/drivers/isdn/hardware/mISDN/w6692.c +++ b/drivers/isdn/hardware/mISDN/w6692.c | |||
@@ -498,16 +498,22 @@ static void | |||
498 | W6692_fill_Bfifo(struct w6692_ch *wch) | 498 | W6692_fill_Bfifo(struct w6692_ch *wch) |
499 | { | 499 | { |
500 | struct w6692_hw *card = wch->bch.hw; | 500 | struct w6692_hw *card = wch->bch.hw; |
501 | int count; | 501 | int count, fillempty = 0; |
502 | u8 *ptr, cmd = W_B_CMDR_RACT | W_B_CMDR_XMS; | 502 | u8 *ptr, cmd = W_B_CMDR_RACT | W_B_CMDR_XMS; |
503 | 503 | ||
504 | pr_debug("%s: fill Bfifo\n", card->name); | 504 | pr_debug("%s: fill Bfifo\n", card->name); |
505 | if (!wch->bch.tx_skb) | 505 | if (!wch->bch.tx_skb) { |
506 | return; | 506 | if (!test_bit(FLG_TX_EMPTY, &wch->bch.Flags)) |
507 | count = wch->bch.tx_skb->len - wch->bch.tx_idx; | 507 | return; |
508 | if (count <= 0) | 508 | ptr = wch->bch.fill; |
509 | return; | 509 | count = W_B_FIFO_THRESH; |
510 | ptr = wch->bch.tx_skb->data + wch->bch.tx_idx; | 510 | fillempty = 1; |
511 | } else { | ||
512 | count = wch->bch.tx_skb->len - wch->bch.tx_idx; | ||
513 | if (count <= 0) | ||
514 | return; | ||
515 | ptr = wch->bch.tx_skb->data + wch->bch.tx_idx; | ||
516 | } | ||
511 | if (count > W_B_FIFO_THRESH) | 517 | if (count > W_B_FIFO_THRESH) |
512 | count = W_B_FIFO_THRESH; | 518 | count = W_B_FIFO_THRESH; |
513 | else if (test_bit(FLG_HDLC, &wch->bch.Flags)) | 519 | else if (test_bit(FLG_HDLC, &wch->bch.Flags)) |
@@ -516,9 +522,16 @@ W6692_fill_Bfifo(struct w6692_ch *wch) | |||
516 | pr_debug("%s: fill Bfifo%d/%d\n", card->name, | 522 | pr_debug("%s: fill Bfifo%d/%d\n", card->name, |
517 | count, wch->bch.tx_idx); | 523 | count, wch->bch.tx_idx); |
518 | wch->bch.tx_idx += count; | 524 | wch->bch.tx_idx += count; |
519 | outsb(wch->addr + W_B_XFIFO, ptr, count); | 525 | if (fillempty) { |
526 | while (count > 0) { | ||
527 | outsb(wch->addr + W_B_XFIFO, ptr, MISDN_BCH_FILL_SIZE); | ||
528 | count -= MISDN_BCH_FILL_SIZE; | ||
529 | } | ||
530 | } else { | ||
531 | outsb(wch->addr + W_B_XFIFO, ptr, count); | ||
532 | } | ||
520 | WriteW6692B(wch, W_B_CMDR, cmd); | 533 | WriteW6692B(wch, W_B_CMDR, cmd); |
521 | if (debug & DEBUG_HW_DFIFO) { | 534 | if ((debug & DEBUG_HW_BFIFO) && !fillempty) { |
522 | snprintf(card->log, 63, "B%1d-send %s %d ", | 535 | snprintf(card->log, 63, "B%1d-send %s %d ", |
523 | wch->bch.nr, card->name, count); | 536 | wch->bch.nr, card->name, count); |
524 | print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, ptr, count); | 537 | print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, ptr, count); |
@@ -637,8 +650,12 @@ send_next(struct w6692_ch *wch) | |||
637 | } else { | 650 | } else { |
638 | if (wch->bch.tx_skb) | 651 | if (wch->bch.tx_skb) |
639 | dev_kfree_skb(wch->bch.tx_skb); | 652 | dev_kfree_skb(wch->bch.tx_skb); |
640 | if (get_next_bframe(&wch->bch)) | 653 | if (get_next_bframe(&wch->bch)) { |
654 | W6692_fill_Bfifo(wch); | ||
655 | test_and_clear_bit(FLG_TX_EMPTY, &wch->bch.Flags); | ||
656 | } else if (test_bit(FLG_TX_EMPTY, &wch->bch.Flags)) { | ||
641 | W6692_fill_Bfifo(wch); | 657 | W6692_fill_Bfifo(wch); |
658 | } | ||
642 | } | 659 | } |
643 | } | 660 | } |
644 | 661 | ||
@@ -727,8 +744,8 @@ W6692B_interrupt(struct w6692_hw *card, int ch) | |||
727 | wch->bch.nr, star); | 744 | wch->bch.nr, star); |
728 | } | 745 | } |
729 | if (star & W_B_STAR_XDOW) { | 746 | if (star & W_B_STAR_XDOW) { |
730 | pr_debug("%s: B%d XDOW proto=%x\n", card->name, | 747 | pr_warning("%s: B%d XDOW proto=%x\n", card->name, |
731 | wch->bch.nr, wch->bch.state); | 748 | wch->bch.nr, wch->bch.state); |
732 | #ifdef ERROR_STATISTIC | 749 | #ifdef ERROR_STATISTIC |
733 | wch->bch.err_xdu++; | 750 | wch->bch.err_xdu++; |
734 | #endif | 751 | #endif |
@@ -741,20 +758,21 @@ W6692B_interrupt(struct w6692_hw *card, int ch) | |||
741 | } | 758 | } |
742 | } | 759 | } |
743 | send_next(wch); | 760 | send_next(wch); |
744 | if (stat & W_B_EXI_XDUN) | 761 | if (star & W_B_STAR_XDOW) |
745 | return; /* handle XDOW only once */ | 762 | return; /* handle XDOW only once */ |
746 | } | 763 | } |
747 | if (stat & W_B_EXI_XDUN) { | 764 | if (stat & W_B_EXI_XDUN) { |
748 | pr_debug("%s: B%d XDUN proto=%x\n", card->name, | 765 | pr_warning("%s: B%d XDUN proto=%x\n", card->name, |
749 | wch->bch.nr, wch->bch.state); | 766 | wch->bch.nr, wch->bch.state); |
750 | #ifdef ERROR_STATISTIC | 767 | #ifdef ERROR_STATISTIC |
751 | wch->bch.err_xdu++; | 768 | wch->bch.err_xdu++; |
752 | #endif | 769 | #endif |
753 | WriteW6692B(wch, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT); | 770 | /* resend - no XRST needed */ |
754 | /* resend */ | ||
755 | if (wch->bch.tx_skb) { | 771 | if (wch->bch.tx_skb) { |
756 | if (!test_bit(FLG_TRANSPARENT, &wch->bch.Flags)) | 772 | if (!test_bit(FLG_TRANSPARENT, &wch->bch.Flags)) |
757 | wch->bch.tx_idx = 0; | 773 | wch->bch.tx_idx = 0; |
774 | } else if (test_bit(FLG_FILLEMPTY, &wch->bch.Flags)) { | ||
775 | test_and_set_bit(FLG_TX_EMPTY, &wch->bch.Flags); | ||
758 | } | 776 | } |
759 | send_next(wch); | 777 | send_next(wch); |
760 | } | 778 | } |
@@ -993,7 +1011,6 @@ open_bchannel(struct w6692_hw *card, struct channel_req *rq) | |||
993 | bch = &card->bc[rq->adr.channel - 1].bch; | 1011 | bch = &card->bc[rq->adr.channel - 1].bch; |
994 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) | 1012 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) |
995 | return -EBUSY; /* b-channel can be only open once */ | 1013 | return -EBUSY; /* b-channel can be only open once */ |
996 | test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags); | ||
997 | bch->ch.protocol = rq->protocol; | 1014 | bch->ch.protocol = rq->protocol; |
998 | rq->ch = &bch->ch; | 1015 | rq->ch = &bch->ch; |
999 | return 0; | 1016 | return 0; |
diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c index 2ac2d7a25a9f..28c99c623bcd 100644 --- a/drivers/isdn/mISDN/dsp_core.c +++ b/drivers/isdn/mISDN/dsp_core.c | |||
@@ -268,6 +268,7 @@ dsp_fill_empty(struct dsp *dsp) | |||
268 | } | 268 | } |
269 | cq.op = MISDN_CTRL_FILL_EMPTY; | 269 | cq.op = MISDN_CTRL_FILL_EMPTY; |
270 | cq.p1 = 1; | 270 | cq.p1 = 1; |
271 | cq.p2 = dsp_silence; | ||
271 | if (dsp->ch.peer->ctrl(dsp->ch.peer, CONTROL_CHANNEL, &cq)) { | 272 | if (dsp->ch.peer->ctrl(dsp->ch.peer, CONTROL_CHANNEL, &cq)) { |
272 | printk(KERN_DEBUG "%s: CONTROL_CHANNEL failed\n", | 273 | printk(KERN_DEBUG "%s: CONTROL_CHANNEL failed\n", |
273 | __func__); | 274 | __func__); |
diff --git a/drivers/isdn/mISDN/hwchannel.c b/drivers/isdn/mISDN/hwchannel.c index d42ad0e98de3..e541b65f68ba 100644 --- a/drivers/isdn/mISDN/hwchannel.c +++ b/drivers/isdn/mISDN/hwchannel.c | |||
@@ -140,6 +140,8 @@ mISDN_clear_bchannel(struct bchannel *ch) | |||
140 | test_and_clear_bit(FLG_TX_BUSY, &ch->Flags); | 140 | test_and_clear_bit(FLG_TX_BUSY, &ch->Flags); |
141 | test_and_clear_bit(FLG_TX_NEXT, &ch->Flags); | 141 | test_and_clear_bit(FLG_TX_NEXT, &ch->Flags); |
142 | test_and_clear_bit(FLG_ACTIVE, &ch->Flags); | 142 | test_and_clear_bit(FLG_ACTIVE, &ch->Flags); |
143 | test_and_clear_bit(FLG_FILLEMPTY, &ch->Flags); | ||
144 | test_and_clear_bit(FLG_TX_EMPTY, &ch->Flags); | ||
143 | ch->minlen = ch->init_minlen; | 145 | ch->minlen = ch->init_minlen; |
144 | ch->next_minlen = ch->init_minlen; | 146 | ch->next_minlen = ch->init_minlen; |
145 | ch->maxlen = ch->init_maxlen; | 147 | ch->maxlen = ch->init_maxlen; |
@@ -165,7 +167,15 @@ mISDN_ctrl_bchannel(struct bchannel *bch, struct mISDN_ctrl_req *cq) | |||
165 | 167 | ||
166 | switch (cq->op) { | 168 | switch (cq->op) { |
167 | case MISDN_CTRL_GETOP: | 169 | case MISDN_CTRL_GETOP: |
168 | cq->op = MISDN_CTRL_RX_BUFFER; | 170 | cq->op = MISDN_CTRL_RX_BUFFER | MISDN_CTRL_FILL_EMPTY; |
171 | break; | ||
172 | case MISDN_CTRL_FILL_EMPTY: | ||
173 | if (cq->p1) { | ||
174 | memset(bch->fill, cq->p2 & 0xff, MISDN_BCH_FILL_SIZE); | ||
175 | test_and_set_bit(FLG_FILLEMPTY, &bch->Flags); | ||
176 | } else { | ||
177 | test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags); | ||
178 | } | ||
169 | break; | 179 | break; |
170 | case MISDN_CTRL_RX_BUFFER: | 180 | case MISDN_CTRL_RX_BUFFER: |
171 | if (cq->p2 > MISDN_CTRL_RX_SIZE_IGNORE) | 181 | if (cq->p2 > MISDN_CTRL_RX_SIZE_IGNORE) |