aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/hardware/mISDN/w6692.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/isdn/hardware/mISDN/w6692.c')
-rw-r--r--drivers/isdn/hardware/mISDN/w6692.c53
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
498W6692_fill_Bfifo(struct w6692_ch *wch) 498W6692_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;