Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8bfddfbe authored by Karsten Keil's avatar Karsten Keil Committed by David S. Miller
Browse files

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: default avatarKarsten Keil <kkeil@linux-pingi.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1368112c
Loading
Loading
Loading
Loading
+6 −15
Original line number Diff line number Diff line
@@ -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,21 +655,16 @@ 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);
		return ret;
	case PH_ACTIVATE_REQ:
+5 −16
Original line number Diff line number Diff line
@@ -2166,13 +2166,9 @@ hfcmulti_tx(struct hfc_multi *hc, int ch)
		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,18 +3487,12 @@ 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);
		return ret;
	case PH_ACTIVATE_REQ:
+3 −11
Original line number Diff line number Diff line
@@ -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,21 +1688,16 @@ 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);
		return ret;
	case PH_ACTIVATE_REQ:
+2 −13
Original line number Diff line number Diff line
@@ -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,14 +1358,10 @@ 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);
		if (errcode < 0) {
			if (debug & DEBUG_HW)
+6 −15
Original line number Diff line number Diff line
@@ -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,21 +1338,16 @@ 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);
		return ret;
	case PH_ACTIVATE_REQ:
Loading