diff options
Diffstat (limited to 'drivers/isdn/hardware/mISDN/w6692.c')
-rw-r--r-- | drivers/isdn/hardware/mISDN/w6692.c | 53 |
1 files changed, 35 insertions, 18 deletions
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; |