aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorKarsten Keil <kkeil@linux-pingi.de>2012-05-15 19:51:02 -0400
committerDavid S. Miller <davem@davemloft.net>2012-05-16 15:22:29 -0400
commit8bfddfbe2100862fd39b97001d0559ccd4c77f19 (patch)
tree587d69b18f6b7ed23eb02577f1d531c626c36216 /drivers
parent1368112c07bae879fa3d1c21f236ca8eea3e5e84 (diff)
mISDN: Early confirm for transparent data
It is better to send a confirm for transparent data early as possible to avoid TX underuns. Signed-off-by: Karsten Keil <kkeil@linux-pingi.de> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/isdn/hardware/mISDN/avmfritz.c21
-rw-r--r--drivers/isdn/hardware/mISDN/hfcmulti.c21
-rw-r--r--drivers/isdn/hardware/mISDN/hfcpci.c14
-rw-r--r--drivers/isdn/hardware/mISDN/hfcsusb.c15
-rw-r--r--drivers/isdn/hardware/mISDN/mISDNipac.c21
-rw-r--r--drivers/isdn/hardware/mISDN/mISDNisar.c18
-rw-r--r--drivers/isdn/hardware/mISDN/netjet.c21
-rw-r--r--drivers/isdn/hardware/mISDN/w6692.c21
-rw-r--r--drivers/isdn/mISDN/hwchannel.c8
9 files changed, 43 insertions, 117 deletions
diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c
index 2271f2b7d501..788b9a7c4df5 100644
--- a/drivers/isdn/hardware/mISDN/avmfritz.c
+++ b/drivers/isdn/hardware/mISDN/avmfritz.c
@@ -488,15 +488,11 @@ hdlc_fill_fifo(struct bchannel *bch)
488static void 488static void
489HDLC_irq_xpr(struct bchannel *bch) 489HDLC_irq_xpr(struct bchannel *bch)
490{ 490{
491 if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len) 491 if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len) {
492 hdlc_fill_fifo(bch); 492 hdlc_fill_fifo(bch);
493 else { 493 } else {
494 if (bch->tx_skb) { 494 if (bch->tx_skb)
495 /* send confirm, on trans, free on hdlc. */
496 if (test_bit(FLG_TRANSPARENT, &bch->Flags))
497 confirm_Bsend(bch);
498 dev_kfree_skb(bch->tx_skb); 495 dev_kfree_skb(bch->tx_skb);
499 }
500 if (get_next_bframe(bch)) 496 if (get_next_bframe(bch))
501 hdlc_fill_fifo(bch); 497 hdlc_fill_fifo(bch);
502 } 498 }
@@ -659,22 +655,17 @@ avm_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
659 struct fritzcard *fc = bch->hw; 655 struct fritzcard *fc = bch->hw;
660 int ret = -EINVAL; 656 int ret = -EINVAL;
661 struct mISDNhead *hh = mISDN_HEAD_P(skb); 657 struct mISDNhead *hh = mISDN_HEAD_P(skb);
662 u32 id; 658 unsigned long flags;
663 u_long flags;
664 659
665 switch (hh->prim) { 660 switch (hh->prim) {
666 case PH_DATA_REQ: 661 case PH_DATA_REQ:
667 spin_lock_irqsave(&fc->lock, flags); 662 spin_lock_irqsave(&fc->lock, flags);
668 ret = bchannel_senddata(bch, skb); 663 ret = bchannel_senddata(bch, skb);
669 if (ret > 0) { /* direct TX */ 664 if (ret > 0) { /* direct TX */
670 id = hh->id; /* skb can be freed */
671 hdlc_fill_fifo(bch); 665 hdlc_fill_fifo(bch);
672 ret = 0; 666 ret = 0;
673 spin_unlock_irqrestore(&fc->lock, flags); 667 }
674 if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) 668 spin_unlock_irqrestore(&fc->lock, flags);
675 queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
676 } else
677 spin_unlock_irqrestore(&fc->lock, flags);
678 return ret; 669 return ret;
679 case PH_ACTIVATE_REQ: 670 case PH_ACTIVATE_REQ:
680 spin_lock_irqsave(&fc->lock, flags); 671 spin_lock_irqsave(&fc->lock, flags);
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index 1dae761d973e..ab3d2983e3ad 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -2166,13 +2166,9 @@ next_frame:
2166 HFC_wait_nodebug(hc); 2166 HFC_wait_nodebug(hc);
2167 } 2167 }
2168 2168
2169 /* send confirm, since get_net_bframe will not do it with trans */
2170 if (bch && test_bit(FLG_TRANSPARENT, &bch->Flags))
2171 confirm_Bsend(bch);
2172
2173 /* check for next frame */
2174 dev_kfree_skb(*sp); 2169 dev_kfree_skb(*sp);
2175 if (bch && get_next_bframe(bch)) { /* hdlc is confirmed here */ 2170 /* check for next frame */
2171 if (bch && get_next_bframe(bch)) {
2176 len = (*sp)->len; 2172 len = (*sp)->len;
2177 goto next_frame; 2173 goto next_frame;
2178 } 2174 }
@@ -3482,8 +3478,7 @@ handle_bmsg(struct mISDNchannel *ch, struct sk_buff *skb)
3482 struct hfc_multi *hc = bch->hw; 3478 struct hfc_multi *hc = bch->hw;
3483 int ret = -EINVAL; 3479 int ret = -EINVAL;
3484 struct mISDNhead *hh = mISDN_HEAD_P(skb); 3480 struct mISDNhead *hh = mISDN_HEAD_P(skb);
3485 unsigned int id; 3481 unsigned long flags;
3486 u_long flags;
3487 3482
3488 switch (hh->prim) { 3483 switch (hh->prim) {
3489 case PH_DATA_REQ: 3484 case PH_DATA_REQ:
@@ -3492,19 +3487,13 @@ handle_bmsg(struct mISDNchannel *ch, struct sk_buff *skb)
3492 spin_lock_irqsave(&hc->lock, flags); 3487 spin_lock_irqsave(&hc->lock, flags);
3493 ret = bchannel_senddata(bch, skb); 3488 ret = bchannel_senddata(bch, skb);
3494 if (ret > 0) { /* direct TX */ 3489 if (ret > 0) { /* direct TX */
3495 id = hh->id; /* skb can be freed */
3496 hfcmulti_tx(hc, bch->slot); 3490 hfcmulti_tx(hc, bch->slot);
3497 ret = 0; 3491 ret = 0;
3498 /* start fifo */ 3492 /* start fifo */
3499 HFC_outb_nodebug(hc, R_FIFO, 0); 3493 HFC_outb_nodebug(hc, R_FIFO, 0);
3500 HFC_wait_nodebug(hc); 3494 HFC_wait_nodebug(hc);
3501 if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) { 3495 }
3502 spin_unlock_irqrestore(&hc->lock, flags); 3496 spin_unlock_irqrestore(&hc->lock, flags);
3503 queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
3504 } else
3505 spin_unlock_irqrestore(&hc->lock, flags);
3506 } else
3507 spin_unlock_irqrestore(&hc->lock, flags);
3508 return ret; 3497 return ret;
3509 case PH_ACTIVATE_REQ: 3498 case PH_ACTIVATE_REQ:
3510 if (debug & DEBUG_HFCMULTI_MSG) 3499 if (debug & DEBUG_HFCMULTI_MSG)
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index f7a5ea7988ed..123e8e5e57be 100644
--- a/drivers/isdn/hardware/mISDN/hfcpci.c
+++ b/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -849,9 +849,6 @@ hfcpci_fill_fifo(struct bchannel *bch)
849 *z1t = cpu_to_le16(new_z1); /* now send data */ 849 *z1t = cpu_to_le16(new_z1); /* now send data */
850 if (bch->tx_idx < bch->tx_skb->len) 850 if (bch->tx_idx < bch->tx_skb->len)
851 return; 851 return;
852 /* send confirm, on trans, free on hdlc. */
853 if (test_bit(FLG_TRANSPARENT, &bch->Flags))
854 confirm_Bsend(bch);
855 dev_kfree_skb(bch->tx_skb); 852 dev_kfree_skb(bch->tx_skb);
856 if (get_next_bframe(bch)) 853 if (get_next_bframe(bch))
857 goto next_t_frame; 854 goto next_t_frame;
@@ -1691,22 +1688,17 @@ hfcpci_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
1691 struct hfc_pci *hc = bch->hw; 1688 struct hfc_pci *hc = bch->hw;
1692 int ret = -EINVAL; 1689 int ret = -EINVAL;
1693 struct mISDNhead *hh = mISDN_HEAD_P(skb); 1690 struct mISDNhead *hh = mISDN_HEAD_P(skb);
1694 unsigned int id; 1691 unsigned long flags;
1695 u_long flags;
1696 1692
1697 switch (hh->prim) { 1693 switch (hh->prim) {
1698 case PH_DATA_REQ: 1694 case PH_DATA_REQ:
1699 spin_lock_irqsave(&hc->lock, flags); 1695 spin_lock_irqsave(&hc->lock, flags);
1700 ret = bchannel_senddata(bch, skb); 1696 ret = bchannel_senddata(bch, skb);
1701 if (ret > 0) { /* direct TX */ 1697 if (ret > 0) { /* direct TX */
1702 id = hh->id; /* skb can be freed */
1703 hfcpci_fill_fifo(bch); 1698 hfcpci_fill_fifo(bch);
1704 ret = 0; 1699 ret = 0;
1705 spin_unlock_irqrestore(&hc->lock, flags); 1700 }
1706 if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) 1701 spin_unlock_irqrestore(&hc->lock, flags);
1707 queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
1708 } else
1709 spin_unlock_irqrestore(&hc->lock, flags);
1710 return ret; 1702 return ret;
1711 case PH_ACTIVATE_REQ: 1703 case PH_ACTIVATE_REQ:
1712 spin_lock_irqsave(&hc->lock, flags); 1704 spin_lock_irqsave(&hc->lock, flags);
diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c
index add28acd54d7..a4c5b24b2266 100644
--- a/drivers/isdn/hardware/mISDN/hfcsusb.c
+++ b/drivers/isdn/hardware/mISDN/hfcsusb.c
@@ -226,15 +226,8 @@ hfcusb_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
226 if (debug & DBG_HFC_CALL_TRACE) 226 if (debug & DBG_HFC_CALL_TRACE)
227 printk(KERN_DEBUG "%s: %s PH_DATA_REQ ret(%i)\n", 227 printk(KERN_DEBUG "%s: %s PH_DATA_REQ ret(%i)\n",
228 hw->name, __func__, ret); 228 hw->name, __func__, ret);
229 if (ret > 0) { 229 if (ret > 0)
230 /*
231 * other l1 drivers don't send early confirms on
232 * transp data, but hfcsusb does because tx_next
233 * skb is needed in tx_iso_complete()
234 */
235 queue_ch_frame(ch, PH_DATA_CNF, hh->id, NULL);
236 ret = 0; 230 ret = 0;
237 }
238 return ret; 231 return ret;
239 case PH_ACTIVATE_REQ: 232 case PH_ACTIVATE_REQ:
240 if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags)) { 233 if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags)) {
@@ -1365,12 +1358,8 @@ tx_iso_complete(struct urb *urb)
1365 if (fifo->dch && get_next_dframe(fifo->dch)) 1358 if (fifo->dch && get_next_dframe(fifo->dch))
1366 tx_skb = fifo->dch->tx_skb; 1359 tx_skb = fifo->dch->tx_skb;
1367 else if (fifo->bch && 1360 else if (fifo->bch &&
1368 get_next_bframe(fifo->bch)) { 1361 get_next_bframe(fifo->bch))
1369 if (test_bit(FLG_TRANSPARENT,
1370 &fifo->bch->Flags))
1371 confirm_Bsend(fifo->bch);
1372 tx_skb = fifo->bch->tx_skb; 1362 tx_skb = fifo->bch->tx_skb;
1373 }
1374 } 1363 }
1375 } 1364 }
1376 errcode = usb_submit_urb(urb, GFP_ATOMIC); 1365 errcode = usb_submit_urb(urb, GFP_ATOMIC);
diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c
index 6c044d55536b..e4b6d8d51aae 100644
--- a/drivers/isdn/hardware/mISDN/mISDNipac.c
+++ b/drivers/isdn/hardware/mISDN/mISDNipac.c
@@ -1011,15 +1011,11 @@ hscx_fill_fifo(struct hscx_hw *hscx)
1011static void 1011static void
1012hscx_xpr(struct hscx_hw *hx) 1012hscx_xpr(struct hscx_hw *hx)
1013{ 1013{
1014 if (hx->bch.tx_skb && hx->bch.tx_idx < hx->bch.tx_skb->len) 1014 if (hx->bch.tx_skb && hx->bch.tx_idx < hx->bch.tx_skb->len) {
1015 hscx_fill_fifo(hx); 1015 hscx_fill_fifo(hx);
1016 else { 1016 } else {
1017 if (hx->bch.tx_skb) { 1017 if (hx->bch.tx_skb)
1018 /* send confirm, on trans, free on hdlc. */
1019 if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags))
1020 confirm_Bsend(&hx->bch);
1021 dev_kfree_skb(hx->bch.tx_skb); 1018 dev_kfree_skb(hx->bch.tx_skb);
1022 }
1023 if (get_next_bframe(&hx->bch)) 1019 if (get_next_bframe(&hx->bch))
1024 hscx_fill_fifo(hx); 1020 hscx_fill_fifo(hx);
1025 } 1021 }
@@ -1342,22 +1338,17 @@ hscx_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
1342 struct hscx_hw *hx = container_of(bch, struct hscx_hw, bch); 1338 struct hscx_hw *hx = container_of(bch, struct hscx_hw, bch);
1343 int ret = -EINVAL; 1339 int ret = -EINVAL;
1344 struct mISDNhead *hh = mISDN_HEAD_P(skb); 1340 struct mISDNhead *hh = mISDN_HEAD_P(skb);
1345 u32 id; 1341 unsigned long flags;
1346 u_long flags;
1347 1342
1348 switch (hh->prim) { 1343 switch (hh->prim) {
1349 case PH_DATA_REQ: 1344 case PH_DATA_REQ:
1350 spin_lock_irqsave(hx->ip->hwlock, flags); 1345 spin_lock_irqsave(hx->ip->hwlock, flags);
1351 ret = bchannel_senddata(bch, skb); 1346 ret = bchannel_senddata(bch, skb);
1352 if (ret > 0) { /* direct TX */ 1347 if (ret > 0) { /* direct TX */
1353 id = hh->id; /* skb can be freed */
1354 ret = 0; 1348 ret = 0;
1355 hscx_fill_fifo(hx); 1349 hscx_fill_fifo(hx);
1356 spin_unlock_irqrestore(hx->ip->hwlock, flags); 1350 }
1357 if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) 1351 spin_unlock_irqrestore(hx->ip->hwlock, flags);
1358 queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
1359 } else
1360 spin_unlock_irqrestore(hx->ip->hwlock, flags);
1361 return ret; 1352 return ret;
1362 case PH_ACTIVATE_REQ: 1353 case PH_ACTIVATE_REQ:
1363 spin_lock_irqsave(hx->ip->hwlock, flags); 1354 spin_lock_irqsave(hx->ip->hwlock, flags);
diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c
index af9a966a1fdf..9deea88c994e 100644
--- a/drivers/isdn/hardware/mISDN/mISDNisar.c
+++ b/drivers/isdn/hardware/mISDN/mISDNisar.c
@@ -702,15 +702,11 @@ send_next(struct isar_ch *ch)
702 } 702 }
703 } 703 }
704 } 704 }
705 if (ch->bch.tx_skb) { 705 if (ch->bch.tx_skb)
706 /* send confirm, on trans, free on hdlc. */
707 if (test_bit(FLG_TRANSPARENT, &ch->bch.Flags))
708 confirm_Bsend(&ch->bch);
709 dev_kfree_skb(ch->bch.tx_skb); 706 dev_kfree_skb(ch->bch.tx_skb);
710 } 707 if (get_next_bframe(&ch->bch)) {
711 if (get_next_bframe(&ch->bch))
712 isar_fill_fifo(ch); 708 isar_fill_fifo(ch);
713 else { 709 } else {
714 if (test_and_clear_bit(FLG_DLEETX, &ch->bch.Flags)) { 710 if (test_and_clear_bit(FLG_DLEETX, &ch->bch.Flags)) {
715 if (test_and_clear_bit(FLG_LASTDATA, 711 if (test_and_clear_bit(FLG_LASTDATA,
716 &ch->bch.Flags)) { 712 &ch->bch.Flags)) {
@@ -1487,14 +1483,10 @@ isar_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
1487 spin_lock_irqsave(ich->is->hwlock, flags); 1483 spin_lock_irqsave(ich->is->hwlock, flags);
1488 ret = bchannel_senddata(bch, skb); 1484 ret = bchannel_senddata(bch, skb);
1489 if (ret > 0) { /* direct TX */ 1485 if (ret > 0) { /* direct TX */
1490 id = hh->id; /* skb can be freed */
1491 ret = 0; 1486 ret = 0;
1492 isar_fill_fifo(ich); 1487 isar_fill_fifo(ich);
1493 spin_unlock_irqrestore(ich->is->hwlock, flags); 1488 }
1494 if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) 1489 spin_unlock_irqrestore(ich->is->hwlock, flags);
1495 queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
1496 } else
1497 spin_unlock_irqrestore(ich->is->hwlock, flags);
1498 return ret; 1490 return ret;
1499 case PH_ACTIVATE_REQ: 1491 case PH_ACTIVATE_REQ:
1500 spin_lock_irqsave(ich->is->hwlock, flags); 1492 spin_lock_irqsave(ich->is->hwlock, flags);
diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c
index 55a77ed7b176..da13b07cd856 100644
--- a/drivers/isdn/hardware/mISDN/netjet.c
+++ b/drivers/isdn/hardware/mISDN/netjet.c
@@ -595,15 +595,11 @@ fill_dma(struct tiger_ch *bc)
595static int 595static int
596bc_next_frame(struct tiger_ch *bc) 596bc_next_frame(struct tiger_ch *bc)
597{ 597{
598 if (bc->bch.tx_skb && bc->bch.tx_idx < bc->bch.tx_skb->len) 598 if (bc->bch.tx_skb && bc->bch.tx_idx < bc->bch.tx_skb->len) {
599 fill_dma(bc); 599 fill_dma(bc);
600 else { 600 } else {
601 if (bc->bch.tx_skb) { 601 if (bc->bch.tx_skb)
602 /* send confirm, on trans, free on hdlc. */
603 if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags))
604 confirm_Bsend(&bc->bch);
605 dev_kfree_skb(bc->bch.tx_skb); 602 dev_kfree_skb(bc->bch.tx_skb);
606 }
607 if (get_next_bframe(&bc->bch)) 603 if (get_next_bframe(&bc->bch))
608 fill_dma(bc); 604 fill_dma(bc);
609 else 605 else
@@ -732,22 +728,17 @@ nj_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
732 struct tiger_ch *bc = container_of(bch, struct tiger_ch, bch); 728 struct tiger_ch *bc = container_of(bch, struct tiger_ch, bch);
733 struct tiger_hw *card = bch->hw; 729 struct tiger_hw *card = bch->hw;
734 struct mISDNhead *hh = mISDN_HEAD_P(skb); 730 struct mISDNhead *hh = mISDN_HEAD_P(skb);
735 u32 id; 731 unsigned long flags;
736 u_long flags;
737 732
738 switch (hh->prim) { 733 switch (hh->prim) {
739 case PH_DATA_REQ: 734 case PH_DATA_REQ:
740 spin_lock_irqsave(&card->lock, flags); 735 spin_lock_irqsave(&card->lock, flags);
741 ret = bchannel_senddata(bch, skb); 736 ret = bchannel_senddata(bch, skb);
742 if (ret > 0) { /* direct TX */ 737 if (ret > 0) { /* direct TX */
743 id = hh->id; /* skb can be freed */
744 fill_dma(bc); 738 fill_dma(bc);
745 ret = 0; 739 ret = 0;
746 spin_unlock_irqrestore(&card->lock, flags); 740 }
747 if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) 741 spin_unlock_irqrestore(&card->lock, flags);
748 queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
749 } else
750 spin_unlock_irqrestore(&card->lock, flags);
751 return ret; 742 return ret;
752 case PH_ACTIVATE_REQ: 743 case PH_ACTIVATE_REQ:
753 spin_lock_irqsave(&card->lock, flags); 744 spin_lock_irqsave(&card->lock, flags);
diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c
index 0b5e9297e95b..f1c0bf1ac689 100644
--- a/drivers/isdn/hardware/mISDN/w6692.c
+++ b/drivers/isdn/hardware/mISDN/w6692.c
@@ -638,15 +638,11 @@ w6692_mode(struct w6692_ch *wch, u32 pr)
638static void 638static void
639send_next(struct w6692_ch *wch) 639send_next(struct w6692_ch *wch)
640{ 640{
641 if (wch->bch.tx_skb && wch->bch.tx_idx < wch->bch.tx_skb->len) 641 if (wch->bch.tx_skb && wch->bch.tx_idx < wch->bch.tx_skb->len) {
642 W6692_fill_Bfifo(wch); 642 W6692_fill_Bfifo(wch);
643 else { 643 } else {
644 if (wch->bch.tx_skb) { 644 if (wch->bch.tx_skb)
645 /* send confirm, on trans, free on hdlc. */
646 if (test_bit(FLG_TRANSPARENT, &wch->bch.Flags))
647 confirm_Bsend(&wch->bch);
648 dev_kfree_skb(wch->bch.tx_skb); 645 dev_kfree_skb(wch->bch.tx_skb);
649 }
650 if (get_next_bframe(&wch->bch)) 646 if (get_next_bframe(&wch->bch))
651 W6692_fill_Bfifo(wch); 647 W6692_fill_Bfifo(wch);
652 } 648 }
@@ -944,22 +940,17 @@ w6692_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
944 struct w6692_hw *card = bch->hw; 940 struct w6692_hw *card = bch->hw;
945 int ret = -EINVAL; 941 int ret = -EINVAL;
946 struct mISDNhead *hh = mISDN_HEAD_P(skb); 942 struct mISDNhead *hh = mISDN_HEAD_P(skb);
947 u32 id; 943 unsigned long flags;
948 u_long flags;
949 944
950 switch (hh->prim) { 945 switch (hh->prim) {
951 case PH_DATA_REQ: 946 case PH_DATA_REQ:
952 spin_lock_irqsave(&card->lock, flags); 947 spin_lock_irqsave(&card->lock, flags);
953 ret = bchannel_senddata(bch, skb); 948 ret = bchannel_senddata(bch, skb);
954 if (ret > 0) { /* direct TX */ 949 if (ret > 0) { /* direct TX */
955 id = hh->id; /* skb can be freed */
956 ret = 0; 950 ret = 0;
957 W6692_fill_Bfifo(bc); 951 W6692_fill_Bfifo(bc);
958 spin_unlock_irqrestore(&card->lock, flags); 952 }
959 if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) 953 spin_unlock_irqrestore(&card->lock, flags);
960 queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
961 } else
962 spin_unlock_irqrestore(&card->lock, flags);
963 return ret; 954 return ret;
964 case PH_ACTIVATE_REQ: 955 case PH_ACTIVATE_REQ:
965 spin_lock_irqsave(&card->lock, flags); 956 spin_lock_irqsave(&card->lock, flags);
diff --git a/drivers/isdn/mISDN/hwchannel.c b/drivers/isdn/mISDN/hwchannel.c
index c74c363554c4..5c5ab478f66a 100644
--- a/drivers/isdn/mISDN/hwchannel.c
+++ b/drivers/isdn/mISDN/hwchannel.c
@@ -272,7 +272,7 @@ get_next_dframe(struct dchannel *dch)
272} 272}
273EXPORT_SYMBOL(get_next_dframe); 273EXPORT_SYMBOL(get_next_dframe);
274 274
275void 275static void
276confirm_Bsend(struct bchannel *bch) 276confirm_Bsend(struct bchannel *bch)
277{ 277{
278 struct sk_buff *skb; 278 struct sk_buff *skb;
@@ -294,7 +294,6 @@ confirm_Bsend(struct bchannel *bch)
294 skb_queue_tail(&bch->rqueue, skb); 294 skb_queue_tail(&bch->rqueue, skb);
295 schedule_event(bch, FLG_RECVQUEUE); 295 schedule_event(bch, FLG_RECVQUEUE);
296} 296}
297EXPORT_SYMBOL(confirm_Bsend);
298 297
299int 298int
300get_next_bframe(struct bchannel *bch) 299get_next_bframe(struct bchannel *bch)
@@ -305,8 +304,8 @@ get_next_bframe(struct bchannel *bch)
305 if (bch->tx_skb) { 304 if (bch->tx_skb) {
306 bch->next_skb = NULL; 305 bch->next_skb = NULL;
307 test_and_clear_bit(FLG_TX_NEXT, &bch->Flags); 306 test_and_clear_bit(FLG_TX_NEXT, &bch->Flags);
308 if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) 307 /* confirm imediately to allow next data */
309 confirm_Bsend(bch); /* not for transparent */ 308 confirm_Bsend(bch);
310 return 1; 309 return 1;
311 } else { 310 } else {
312 test_and_clear_bit(FLG_TX_NEXT, &bch->Flags); 311 test_and_clear_bit(FLG_TX_NEXT, &bch->Flags);
@@ -395,6 +394,7 @@ bchannel_senddata(struct bchannel *ch, struct sk_buff *skb)
395 /* write to fifo */ 394 /* write to fifo */
396 ch->tx_skb = skb; 395 ch->tx_skb = skb;
397 ch->tx_idx = 0; 396 ch->tx_idx = 0;
397 confirm_Bsend(ch);
398 return 1; 398 return 1;
399 } 399 }
400} 400}