mISDN: Early confirm for transparent data
authorKarsten Keil <kkeil@linux-pingi.de>
Tue, 15 May 2012 23:51:02 +0000 (23:51 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 16 May 2012 19:22:29 +0000 (15:22 -0400)
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>
drivers/isdn/hardware/mISDN/avmfritz.c
drivers/isdn/hardware/mISDN/hfcmulti.c
drivers/isdn/hardware/mISDN/hfcpci.c
drivers/isdn/hardware/mISDN/hfcsusb.c
drivers/isdn/hardware/mISDN/mISDNipac.c
drivers/isdn/hardware/mISDN/mISDNisar.c
drivers/isdn/hardware/mISDN/netjet.c
drivers/isdn/hardware/mISDN/w6692.c
drivers/isdn/mISDN/hwchannel.c
include/linux/mISDNhw.h

index 2271f2b7d50147ce8c41dce0ffdfc18f0d12868e..788b9a7c4df5ab0dcd50a6d303c164d986914679 100644 (file)
@@ -488,15 +488,11 @@ hdlc_fill_fifo(struct bchannel *bch)
 static void
 HDLC_irq_xpr(struct bchannel *bch)
 {
-       if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len)
+       if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len) {
                hdlc_fill_fifo(bch);
-       else {
-               if (bch->tx_skb) {
-                       /* send confirm, on trans, free on hdlc. */
-                       if (test_bit(FLG_TRANSPARENT, &bch->Flags))
-                               confirm_Bsend(bch);
+       } else {
+               if (bch->tx_skb)
                        dev_kfree_skb(bch->tx_skb);
-               }
                if (get_next_bframe(bch))
                        hdlc_fill_fifo(bch);
        }
@@ -659,22 +655,17 @@ avm_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
        struct fritzcard *fc = bch->hw;
        int ret = -EINVAL;
        struct mISDNhead *hh = mISDN_HEAD_P(skb);
-       u32 id;
-       u_long flags;
+       unsigned long flags;
 
        switch (hh->prim) {
        case PH_DATA_REQ:
                spin_lock_irqsave(&fc->lock, flags);
                ret = bchannel_senddata(bch, skb);
                if (ret > 0) { /* direct TX */
-                       id = hh->id; /* skb can be freed */
                        hdlc_fill_fifo(bch);
                        ret = 0;
-                       spin_unlock_irqrestore(&fc->lock, flags);
-                       if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
-                               queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
-               } else
-                       spin_unlock_irqrestore(&fc->lock, flags);
+               }
+               spin_unlock_irqrestore(&fc->lock, flags);
                return ret;
        case PH_ACTIVATE_REQ:
                spin_lock_irqsave(&fc->lock, flags);
index 1dae761d973e99e0d3ccf394f87ac37898c6fc23..ab3d2983e3ada74b0a4b3bc0ad749f2f2a628ac0 100644 (file)
@@ -2166,13 +2166,9 @@ next_frame:
                HFC_wait_nodebug(hc);
        }
 
-       /* send confirm, since get_net_bframe will not do it with trans */
-       if (bch && test_bit(FLG_TRANSPARENT, &bch->Flags))
-               confirm_Bsend(bch);
-
-       /* check for next frame */
        dev_kfree_skb(*sp);
-       if (bch && get_next_bframe(bch)) { /* hdlc is confirmed here */
+       /* check for next frame */
+       if (bch && get_next_bframe(bch)) {
                len = (*sp)->len;
                goto next_frame;
        }
@@ -3482,8 +3478,7 @@ handle_bmsg(struct mISDNchannel *ch, struct sk_buff *skb)
        struct hfc_multi        *hc = bch->hw;
        int                     ret = -EINVAL;
        struct mISDNhead        *hh = mISDN_HEAD_P(skb);
-       unsigned int            id;
-       u_long                  flags;
+       unsigned long           flags;
 
        switch (hh->prim) {
        case PH_DATA_REQ:
@@ -3492,19 +3487,13 @@ handle_bmsg(struct mISDNchannel *ch, struct sk_buff *skb)
                spin_lock_irqsave(&hc->lock, flags);
                ret = bchannel_senddata(bch, skb);
                if (ret > 0) { /* direct TX */
-                       id = hh->id; /* skb can be freed */
                        hfcmulti_tx(hc, bch->slot);
                        ret = 0;
                        /* start fifo */
                        HFC_outb_nodebug(hc, R_FIFO, 0);
                        HFC_wait_nodebug(hc);
-                       if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) {
-                               spin_unlock_irqrestore(&hc->lock, flags);
-                               queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
-                       } else
-                               spin_unlock_irqrestore(&hc->lock, flags);
-               } else
-                       spin_unlock_irqrestore(&hc->lock, flags);
+               }
+               spin_unlock_irqrestore(&hc->lock, flags);
                return ret;
        case PH_ACTIVATE_REQ:
                if (debug & DEBUG_HFCMULTI_MSG)
index f7a5ea7988ed7f0ce2de032d8dd80f67cbabe81f..123e8e5e57be16e414dd53f149d7087e4355e3b2 100644 (file)
@@ -849,9 +849,6 @@ hfcpci_fill_fifo(struct bchannel *bch)
                *z1t = cpu_to_le16(new_z1);     /* now send data */
                if (bch->tx_idx < bch->tx_skb->len)
                        return;
-               /* send confirm, on trans, free on hdlc. */
-               if (test_bit(FLG_TRANSPARENT, &bch->Flags))
-                       confirm_Bsend(bch);
                dev_kfree_skb(bch->tx_skb);
                if (get_next_bframe(bch))
                        goto next_t_frame;
@@ -1691,22 +1688,17 @@ hfcpci_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
        struct hfc_pci          *hc = bch->hw;
        int                     ret = -EINVAL;
        struct mISDNhead        *hh = mISDN_HEAD_P(skb);
-       unsigned int            id;
-       u_long                  flags;
+       unsigned long           flags;
 
        switch (hh->prim) {
        case PH_DATA_REQ:
                spin_lock_irqsave(&hc->lock, flags);
                ret = bchannel_senddata(bch, skb);
                if (ret > 0) { /* direct TX */
-                       id = hh->id; /* skb can be freed */
                        hfcpci_fill_fifo(bch);
                        ret = 0;
-                       spin_unlock_irqrestore(&hc->lock, flags);
-                       if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
-                               queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
-               } else
-                       spin_unlock_irqrestore(&hc->lock, flags);
+               }
+               spin_unlock_irqrestore(&hc->lock, flags);
                return ret;
        case PH_ACTIVATE_REQ:
                spin_lock_irqsave(&hc->lock, flags);
index add28acd54d785c4d7a99f1c22679b50df997809..a4c5b24b2266e580df31bc3d37cfa4b4f5bc58d4 100644 (file)
@@ -226,15 +226,8 @@ hfcusb_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
                if (debug & DBG_HFC_CALL_TRACE)
                        printk(KERN_DEBUG "%s: %s PH_DATA_REQ ret(%i)\n",
                               hw->name, __func__, ret);
-               if (ret > 0) {
-                       /*
-                        * other l1 drivers don't send early confirms on
-                        * transp data, but hfcsusb does because tx_next
-                        * skb is needed in tx_iso_complete()
-                        */
-                       queue_ch_frame(ch, PH_DATA_CNF, hh->id, NULL);
+               if (ret > 0)
                        ret = 0;
-               }
                return ret;
        case PH_ACTIVATE_REQ:
                if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags)) {
@@ -1365,12 +1358,8 @@ tx_iso_complete(struct urb *urb)
                                if (fifo->dch && get_next_dframe(fifo->dch))
                                        tx_skb = fifo->dch->tx_skb;
                                else if (fifo->bch &&
-                                        get_next_bframe(fifo->bch)) {
-                                       if (test_bit(FLG_TRANSPARENT,
-                                                    &fifo->bch->Flags))
-                                               confirm_Bsend(fifo->bch);
+                                        get_next_bframe(fifo->bch))
                                        tx_skb = fifo->bch->tx_skb;
-                               }
                        }
                }
                errcode = usb_submit_urb(urb, GFP_ATOMIC);
index 6c044d55536bb9b8b822cbbbd7c96b28e817a00b..e4b6d8d51aaebb31adcbc176b0e8dd9bdb52952c 100644 (file)
@@ -1011,15 +1011,11 @@ hscx_fill_fifo(struct hscx_hw *hscx)
 static void
 hscx_xpr(struct hscx_hw *hx)
 {
-       if (hx->bch.tx_skb && hx->bch.tx_idx < hx->bch.tx_skb->len)
+       if (hx->bch.tx_skb && hx->bch.tx_idx < hx->bch.tx_skb->len) {
                hscx_fill_fifo(hx);
-       else {
-               if (hx->bch.tx_skb) {
-                       /* send confirm, on trans, free on hdlc. */
-                       if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags))
-                               confirm_Bsend(&hx->bch);
+       } else {
+               if (hx->bch.tx_skb)
                        dev_kfree_skb(hx->bch.tx_skb);
-               }
                if (get_next_bframe(&hx->bch))
                        hscx_fill_fifo(hx);
        }
@@ -1342,22 +1338,17 @@ hscx_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
        struct hscx_hw  *hx = container_of(bch, struct hscx_hw, bch);
        int ret = -EINVAL;
        struct mISDNhead *hh = mISDN_HEAD_P(skb);
-       u32 id;
-       u_long flags;
+       unsigned long flags;
 
        switch (hh->prim) {
        case PH_DATA_REQ:
                spin_lock_irqsave(hx->ip->hwlock, flags);
                ret = bchannel_senddata(bch, skb);
                if (ret > 0) { /* direct TX */
-                       id = hh->id; /* skb can be freed */
                        ret = 0;
                        hscx_fill_fifo(hx);
-                       spin_unlock_irqrestore(hx->ip->hwlock, flags);
-                       if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
-                               queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
-               } else
-                       spin_unlock_irqrestore(hx->ip->hwlock, flags);
+               }
+               spin_unlock_irqrestore(hx->ip->hwlock, flags);
                return ret;
        case PH_ACTIVATE_REQ:
                spin_lock_irqsave(hx->ip->hwlock, flags);
index af9a966a1fdf242ff04d94bdeac6bc09c0b55389..9deea88c994e28ab521d4565c4ac598a2ef3222e 100644 (file)
@@ -702,15 +702,11 @@ send_next(struct isar_ch *ch)
                        }
                }
        }
-       if (ch->bch.tx_skb) {
-               /* send confirm, on trans, free on hdlc. */
-               if (test_bit(FLG_TRANSPARENT, &ch->bch.Flags))
-                       confirm_Bsend(&ch->bch);
+       if (ch->bch.tx_skb)
                dev_kfree_skb(ch->bch.tx_skb);
-       }
-       if (get_next_bframe(&ch->bch))
+       if (get_next_bframe(&ch->bch)) {
                isar_fill_fifo(ch);
-       else {
+       else {
                if (test_and_clear_bit(FLG_DLEETX, &ch->bch.Flags)) {
                        if (test_and_clear_bit(FLG_LASTDATA,
                                               &ch->bch.Flags)) {
@@ -1487,14 +1483,10 @@ isar_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
                spin_lock_irqsave(ich->is->hwlock, flags);
                ret = bchannel_senddata(bch, skb);
                if (ret > 0) { /* direct TX */
-                       id = hh->id; /* skb can be freed */
                        ret = 0;
                        isar_fill_fifo(ich);
-                       spin_unlock_irqrestore(ich->is->hwlock, flags);
-                       if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
-                               queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
-               } else
-                       spin_unlock_irqrestore(ich->is->hwlock, flags);
+               }
+               spin_unlock_irqrestore(ich->is->hwlock, flags);
                return ret;
        case PH_ACTIVATE_REQ:
                spin_lock_irqsave(ich->is->hwlock, flags);
index 55a77ed7b176e629a66d7b50421e017fbc5a9e7d..da13b07cd8568e4503ee1d337e5e198d69d47d1f 100644 (file)
@@ -595,15 +595,11 @@ fill_dma(struct tiger_ch *bc)
 static int
 bc_next_frame(struct tiger_ch *bc)
 {
-       if (bc->bch.tx_skb && bc->bch.tx_idx < bc->bch.tx_skb->len)
+       if (bc->bch.tx_skb && bc->bch.tx_idx < bc->bch.tx_skb->len) {
                fill_dma(bc);
-       else {
-               if (bc->bch.tx_skb) {
-                       /* send confirm, on trans, free on hdlc. */
-                       if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags))
-                               confirm_Bsend(&bc->bch);
+       } else {
+               if (bc->bch.tx_skb)
                        dev_kfree_skb(bc->bch.tx_skb);
-               }
                if (get_next_bframe(&bc->bch))
                        fill_dma(bc);
                else
@@ -732,22 +728,17 @@ nj_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
        struct tiger_ch *bc = container_of(bch, struct tiger_ch, bch);
        struct tiger_hw *card = bch->hw;
        struct mISDNhead *hh = mISDN_HEAD_P(skb);
-       u32 id;
-       u_long flags;
+       unsigned long flags;
 
        switch (hh->prim) {
        case PH_DATA_REQ:
                spin_lock_irqsave(&card->lock, flags);
                ret = bchannel_senddata(bch, skb);
                if (ret > 0) { /* direct TX */
-                       id = hh->id; /* skb can be freed */
                        fill_dma(bc);
                        ret = 0;
-                       spin_unlock_irqrestore(&card->lock, flags);
-                       if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
-                               queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
-               } else
-                       spin_unlock_irqrestore(&card->lock, flags);
+               }
+               spin_unlock_irqrestore(&card->lock, flags);
                return ret;
        case PH_ACTIVATE_REQ:
                spin_lock_irqsave(&card->lock, flags);
index 0b5e9297e95b793b17fb4c408c286dceed175baa..f1c0bf1ac6893f439e6ea3e26f4d439eb703161a 100644 (file)
@@ -638,15 +638,11 @@ w6692_mode(struct w6692_ch *wch, u32 pr)
 static void
 send_next(struct w6692_ch *wch)
 {
-       if (wch->bch.tx_skb && wch->bch.tx_idx < wch->bch.tx_skb->len)
+       if (wch->bch.tx_skb && wch->bch.tx_idx < wch->bch.tx_skb->len) {
                W6692_fill_Bfifo(wch);
-       else {
-               if (wch->bch.tx_skb) {
-                       /* send confirm, on trans, free on hdlc. */
-                       if (test_bit(FLG_TRANSPARENT, &wch->bch.Flags))
-                               confirm_Bsend(&wch->bch);
+       } else {
+               if (wch->bch.tx_skb)
                        dev_kfree_skb(wch->bch.tx_skb);
-               }
                if (get_next_bframe(&wch->bch))
                        W6692_fill_Bfifo(wch);
        }
@@ -944,22 +940,17 @@ w6692_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
        struct w6692_hw *card = bch->hw;
        int ret = -EINVAL;
        struct mISDNhead *hh = mISDN_HEAD_P(skb);
-       u32 id;
-       u_long flags;
+       unsigned long flags;
 
        switch (hh->prim) {
        case PH_DATA_REQ:
                spin_lock_irqsave(&card->lock, flags);
                ret = bchannel_senddata(bch, skb);
                if (ret > 0) { /* direct TX */
-                       id = hh->id; /* skb can be freed */
                        ret = 0;
                        W6692_fill_Bfifo(bc);
-                       spin_unlock_irqrestore(&card->lock, flags);
-                       if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
-                               queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
-               } else
-                       spin_unlock_irqrestore(&card->lock, flags);
+               }
+               spin_unlock_irqrestore(&card->lock, flags);
                return ret;
        case PH_ACTIVATE_REQ:
                spin_lock_irqsave(&card->lock, flags);
index c74c363554c4c9506f328968b048682ebd4cdabd..5c5ab478f66aea78910c8f7edd315af59492114c 100644 (file)
@@ -272,7 +272,7 @@ get_next_dframe(struct dchannel *dch)
 }
 EXPORT_SYMBOL(get_next_dframe);
 
-void
+static void
 confirm_Bsend(struct bchannel *bch)
 {
        struct sk_buff  *skb;
@@ -294,7 +294,6 @@ confirm_Bsend(struct bchannel *bch)
        skb_queue_tail(&bch->rqueue, skb);
        schedule_event(bch, FLG_RECVQUEUE);
 }
-EXPORT_SYMBOL(confirm_Bsend);
 
 int
 get_next_bframe(struct bchannel *bch)
@@ -305,8 +304,8 @@ get_next_bframe(struct bchannel *bch)
                if (bch->tx_skb) {
                        bch->next_skb = NULL;
                        test_and_clear_bit(FLG_TX_NEXT, &bch->Flags);
-                       if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
-                               confirm_Bsend(bch); /* not for transparent */
+                       /* confirm imediately to allow next data */
+                       confirm_Bsend(bch);
                        return 1;
                } else {
                        test_and_clear_bit(FLG_TX_NEXT, &bch->Flags);
@@ -395,6 +394,7 @@ bchannel_senddata(struct bchannel *ch, struct sk_buff *skb)
                /* write to fifo */
                ch->tx_skb = skb;
                ch->tx_idx = 0;
+               confirm_Bsend(ch);
                return 1;
        }
 }
index de165b54237b06d79b61bf69d42f6184bb8dce93..491afd6d5709c199c84a2d24368b60a5e2fcfc5d 100644 (file)
@@ -182,7 +182,6 @@ extern void recv_Echannel(struct dchannel *, struct dchannel *);
 extern void    recv_Bchannel(struct bchannel *, unsigned int id);
 extern void    recv_Dchannel_skb(struct dchannel *, struct sk_buff *);
 extern void    recv_Bchannel_skb(struct bchannel *, struct sk_buff *);
-extern void    confirm_Bsend(struct bchannel *bch);
 extern int     get_next_bframe(struct bchannel *);
 extern int     get_next_dframe(struct dchannel *);