diff options
author | Karsten Keil <kkeil@linux-pingi.de> | 2012-05-15 19:51:02 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-05-16 15:22:29 -0400 |
commit | 8bfddfbe2100862fd39b97001d0559ccd4c77f19 (patch) | |
tree | 587d69b18f6b7ed23eb02577f1d531c626c36216 /drivers | |
parent | 1368112c07bae879fa3d1c21f236ca8eea3e5e84 (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.c | 21 | ||||
-rw-r--r-- | drivers/isdn/hardware/mISDN/hfcmulti.c | 21 | ||||
-rw-r--r-- | drivers/isdn/hardware/mISDN/hfcpci.c | 14 | ||||
-rw-r--r-- | drivers/isdn/hardware/mISDN/hfcsusb.c | 15 | ||||
-rw-r--r-- | drivers/isdn/hardware/mISDN/mISDNipac.c | 21 | ||||
-rw-r--r-- | drivers/isdn/hardware/mISDN/mISDNisar.c | 18 | ||||
-rw-r--r-- | drivers/isdn/hardware/mISDN/netjet.c | 21 | ||||
-rw-r--r-- | drivers/isdn/hardware/mISDN/w6692.c | 21 | ||||
-rw-r--r-- | drivers/isdn/mISDN/hwchannel.c | 8 |
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) | |||
488 | static void | 488 | static void |
489 | HDLC_irq_xpr(struct bchannel *bch) | 489 | HDLC_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) | |||
1011 | static void | 1011 | static void |
1012 | hscx_xpr(struct hscx_hw *hx) | 1012 | hscx_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) | |||
595 | static int | 595 | static int |
596 | bc_next_frame(struct tiger_ch *bc) | 596 | bc_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) | |||
638 | static void | 638 | static void |
639 | send_next(struct w6692_ch *wch) | 639 | send_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 | } |
273 | EXPORT_SYMBOL(get_next_dframe); | 273 | EXPORT_SYMBOL(get_next_dframe); |
274 | 274 | ||
275 | void | 275 | static void |
276 | confirm_Bsend(struct bchannel *bch) | 276 | confirm_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 | } |
297 | EXPORT_SYMBOL(confirm_Bsend); | ||
298 | 297 | ||
299 | int | 298 | int |
300 | get_next_bframe(struct bchannel *bch) | 299 | get_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 | } |