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

Commit 034005a0 authored by Karsten Keil's avatar Karsten Keil Committed by David S. Miller
Browse files

mISDN: Allow to set a minimum length for transparent data



If the FIFO of the card is small, many short messages are queued up to
the upper layers and the userspace. This change allows the applications
to set a minimum datalen they want from the drivers.
Create a common control function to avoid code duplication in each
driver.

Signed-off-by: default avatarKarsten Keil <kkeil@linux-pingi.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7206e659
Loading
Loading
Loading
Loading
+13 −22
Original line number Original line Diff line number Diff line
@@ -536,12 +536,12 @@ HDLC_irq(struct bchannel *bch, u32 stat)
			hdlc_empty_fifo(bch, len);
			hdlc_empty_fifo(bch, len);
			if (!bch->rx_skb)
			if (!bch->rx_skb)
				goto handle_tx;
				goto handle_tx;
			if (test_bit(FLG_TRANSPARENT, &bch->Flags) ||
			if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {
			    (stat & HDLC_STAT_RME)) {
				recv_Bchannel(bch, 0, false);
				if (((stat & HDLC_STAT_CRCVFRRAB) ==
			} else if (stat & HDLC_STAT_RME) {
				     HDLC_STAT_CRCVFR) ||
				if ((stat & HDLC_STAT_CRCVFRRAB) ==
				    test_bit(FLG_TRANSPARENT, &bch->Flags)) {
				    HDLC_STAT_CRCVFR) {
					recv_Bchannel(bch, 0);
					recv_Bchannel(bch, 0, false);
				} else {
				} else {
					pr_warning("%s: got invalid frame\n",
					pr_warning("%s: got invalid frame\n",
						   fc->name);
						   fc->name);
@@ -809,21 +809,7 @@ init_card(struct fritzcard *fc)
static int
static int
channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
{
{
	int ret = 0;
	return mISDN_ctrl_bchannel(bch, cq);
	struct fritzcard *fc = bch->hw;

	switch (cq->op) {
	case MISDN_CTRL_GETOP:
		cq->op = 0;
		break;
		/* Nothing implemented yet */
	case MISDN_CTRL_FILL_EMPTY:
	default:
		pr_info("%s: %s unknown Op %x\n", fc->name, __func__, cq->op);
		ret = -EINVAL;
		break;
	}
	return ret;
}
}


static int
static int
@@ -1019,6 +1005,7 @@ static int __devinit
setup_instance(struct fritzcard *card)
setup_instance(struct fritzcard *card)
{
{
	int i, err;
	int i, err;
	unsigned short minsize;
	u_long flags;
	u_long flags;


	snprintf(card->name, MISDN_MAX_IDLEN - 1, "AVM.%d", AVM_cnt + 1);
	snprintf(card->name, MISDN_MAX_IDLEN - 1, "AVM.%d", AVM_cnt + 1);
@@ -1038,7 +1025,11 @@ setup_instance(struct fritzcard *card)
	for (i = 0; i < 2; i++) {
	for (i = 0; i < 2; i++) {
		card->bch[i].nr = i + 1;
		card->bch[i].nr = i + 1;
		set_channelmap(i + 1, card->isac.dch.dev.channelmap);
		set_channelmap(i + 1, card->isac.dch.dev.channelmap);
		mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM);
		if (AVM_FRITZ_PCIV2 == card->type)
			minsize = HDLC_FIFO_SIZE_V2;
		else
			minsize = HDLC_FIFO_SIZE_V1;
		mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM, minsize);
		card->bch[i].hw = card;
		card->bch[i].hw = card;
		card->bch[i].ch.send = avm_l2l1B;
		card->bch[i].ch.send = avm_l2l1B;
		card->bch[i].ch.ctrl = avm_bctrl;
		card->bch[i].ch.ctrl = avm_bctrl;
+8 −9
Original line number Original line Diff line number Diff line
@@ -2352,7 +2352,7 @@ hfcmulti_rx(struct hfc_multi *hc, int ch)
			if (dch)
			if (dch)
				recv_Dchannel(dch);
				recv_Dchannel(dch);
			else
			else
				recv_Bchannel(bch, MISDN_ID_ANY);
				recv_Bchannel(bch, MISDN_ID_ANY, false);
			*sp = skb;
			*sp = skb;
			again++;
			again++;
			goto next_frame;
			goto next_frame;
@@ -2367,7 +2367,7 @@ hfcmulti_rx(struct hfc_multi *hc, int ch)
			       "(z1=%04x, z2=%04x) TRANS\n",
			       "(z1=%04x, z2=%04x) TRANS\n",
			       __func__, hc->id + 1, ch, Zsize, z1, z2);
			       __func__, hc->id + 1, ch, Zsize, z1, z2);
		/* only bch is transparent */
		/* only bch is transparent */
		recv_Bchannel(bch, hc->chan[ch].Zfill);
		recv_Bchannel(bch, hc->chan[ch].Zfill, false);
	}
	}
}
}


@@ -3574,8 +3574,9 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)


	switch (cq->op) {
	switch (cq->op) {
	case MISDN_CTRL_GETOP:
	case MISDN_CTRL_GETOP:
		cq->op = MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP
		ret = mISDN_ctrl_bchannel(bch, cq);
			| MISDN_CTRL_RX_OFF | MISDN_CTRL_FILL_EMPTY;
		cq->op |= MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP |
			  MISDN_CTRL_RX_OFF | MISDN_CTRL_FILL_EMPTY;
		break;
		break;
	case MISDN_CTRL_RX_OFF: /* turn off / on rx stream */
	case MISDN_CTRL_RX_OFF: /* turn off / on rx stream */
		hc->chan[bch->slot].rx_off = !!cq->p1;
		hc->chan[bch->slot].rx_off = !!cq->p1;
@@ -3683,9 +3684,7 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
			ret = -EINVAL;
			ret = -EINVAL;
		break;
		break;
	default:
	default:
		printk(KERN_WARNING "%s: unknown Op %x\n",
		ret = mISDN_ctrl_bchannel(bch, cq);
		       __func__, cq->op);
		ret = -EINVAL;
		break;
		break;
	}
	}
	return ret;
	return ret;
@@ -4855,7 +4854,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m, int pt)
		bch->nr = ch;
		bch->nr = ch;
		bch->slot = ch;
		bch->slot = ch;
		bch->debug = debug;
		bch->debug = debug;
		mISDN_initbchannel(bch, MAX_DATA_MEM);
		mISDN_initbchannel(bch, MAX_DATA_MEM, poll >> 1);
		bch->hw = hc;
		bch->hw = hc;
		bch->ch.send = handle_bmsg;
		bch->ch.send = handle_bmsg;
		bch->ch.ctrl = hfcm_bctrl;
		bch->ch.ctrl = hfcm_bctrl;
@@ -4928,7 +4927,7 @@ init_multi_port(struct hfc_multi *hc, int pt)
		bch->nr = ch + 1;
		bch->nr = ch + 1;
		bch->slot = i + ch;
		bch->slot = i + ch;
		bch->debug = debug;
		bch->debug = debug;
		mISDN_initbchannel(bch, MAX_DATA_MEM);
		mISDN_initbchannel(bch, MAX_DATA_MEM, poll >> 1);
		bch->hw = hc;
		bch->hw = hc;
		bch->ch.send = handle_bmsg;
		bch->ch.send = handle_bmsg;
		bch->ch.ctrl = hfcm_bctrl;
		bch->ch.ctrl = hfcm_bctrl;
+6 −6
Original line number Original line Diff line number Diff line
@@ -453,7 +453,7 @@ hfcpci_empty_bfifo(struct bchannel *bch, struct bzfifo *bz,
		}
		}
		bz->za[new_f2].z2 = cpu_to_le16(new_z2);
		bz->za[new_f2].z2 = cpu_to_le16(new_z2);
		bz->f2 = new_f2;	/* next buffer */
		bz->f2 = new_f2;	/* next buffer */
		recv_Bchannel(bch, MISDN_ID_ANY);
		recv_Bchannel(bch, MISDN_ID_ANY, false);
	}
	}
}
}


@@ -599,7 +599,7 @@ hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *rxbz,
			ptr1 = bdata;	/* start of buffer */
			ptr1 = bdata;	/* start of buffer */
			memcpy(ptr, ptr1, fcnt_rx);	/* rest */
			memcpy(ptr, ptr1, fcnt_rx);	/* rest */
		}
		}
		recv_Bchannel(bch, fcnt_tx); /* bch, id */
		recv_Bchannel(bch, fcnt_tx, false); /* bch, id, !force */
	}
	}
	*z2r = cpu_to_le16(new_z2);		/* new position */
	*z2r = cpu_to_le16(new_z2);		/* new position */
}
}
@@ -1535,7 +1535,8 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)


	switch (cq->op) {
	switch (cq->op) {
	case MISDN_CTRL_GETOP:
	case MISDN_CTRL_GETOP:
		cq->op = MISDN_CTRL_FILL_EMPTY;
		ret = mISDN_ctrl_bchannel(bch, cq);
		cq->op |= MISDN_CTRL_FILL_EMPTY;
		break;
		break;
	case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */
	case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */
		test_and_set_bit(FLG_FILLEMPTY, &bch->Flags);
		test_and_set_bit(FLG_FILLEMPTY, &bch->Flags);
@@ -1544,8 +1545,7 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
			       "off=%d)\n", __func__, bch->nr, !!cq->p1);
			       "off=%d)\n", __func__, bch->nr, !!cq->p1);
		break;
		break;
	default:
	default:
		printk(KERN_WARNING "%s: unknown Op %x\n", __func__, cq->op);
		ret = mISDN_ctrl_bchannel(bch, cq);
		ret = -EINVAL;
		break;
		break;
	}
	}
	return ret;
	return ret;
@@ -2116,7 +2116,7 @@ setup_card(struct hfc_pci *card)
		card->bch[i].nr = i + 1;
		card->bch[i].nr = i + 1;
		set_channelmap(i + 1, card->dch.dev.channelmap);
		set_channelmap(i + 1, card->dch.dev.channelmap);
		card->bch[i].debug = debug;
		card->bch[i].debug = debug;
		mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM);
		mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM, poll >> 1);
		card->bch[i].hw = card;
		card->bch[i].hw = card;
		card->bch[i].ch.send = hfcpci_l2l1B;
		card->bch[i].ch.send = hfcpci_l2l1B;
		card->bch[i].ch.ctrl = hfc_bctrl;
		card->bch[i].ch.ctrl = hfc_bctrl;
+7 −7
Original line number Original line Diff line number Diff line
@@ -810,7 +810,8 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)


	switch (cq->op) {
	switch (cq->op) {
	case MISDN_CTRL_GETOP:
	case MISDN_CTRL_GETOP:
		cq->op = MISDN_CTRL_FILL_EMPTY;
		ret = mISDN_ctrl_bchannel(bch, cq);
		cq->op |= MISDN_CTRL_FILL_EMPTY;
		break;
		break;
	case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */
	case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */
		test_and_set_bit(FLG_FILLEMPTY, &bch->Flags);
		test_and_set_bit(FLG_FILLEMPTY, &bch->Flags);
@@ -819,8 +820,7 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
			       "off=%d)\n", __func__, bch->nr, !!cq->p1);
			       "off=%d)\n", __func__, bch->nr, !!cq->p1);
		break;
		break;
	default:
	default:
		printk(KERN_WARNING "%s: unknown Op %x\n", __func__, cq->op);
		ret = mISDN_ctrl_bchannel(bch, cq);
		ret = -EINVAL;
		break;
		break;
	}
	}
	return ret;
	return ret;
@@ -931,7 +931,8 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
				if (fifo->dch)
				if (fifo->dch)
					recv_Dchannel(fifo->dch);
					recv_Dchannel(fifo->dch);
				if (fifo->bch)
				if (fifo->bch)
					recv_Bchannel(fifo->bch, MISDN_ID_ANY);
					recv_Bchannel(fifo->bch, MISDN_ID_ANY,
						      0);
				if (fifo->ech)
				if (fifo->ech)
					recv_Echannel(fifo->ech,
					recv_Echannel(fifo->ech,
						      &hw->dch);
						      &hw->dch);
@@ -952,8 +953,7 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
		}
		}
	} else {
	} else {
		/* deliver transparent data to layer2 */
		/* deliver transparent data to layer2 */
		if (rx_skb->len >= poll)
		recv_Bchannel(fifo->bch, MISDN_ID_ANY, false);
			recv_Bchannel(fifo->bch, MISDN_ID_ANY);
	}
	}
	spin_unlock(&hw->lock);
	spin_unlock(&hw->lock);
}
}
@@ -1861,7 +1861,7 @@ setup_instance(struct hfcsusb *hw, struct device *parent)
		hw->bch[i].nr = i + 1;
		hw->bch[i].nr = i + 1;
		set_channelmap(i + 1, hw->dch.dev.channelmap);
		set_channelmap(i + 1, hw->dch.dev.channelmap);
		hw->bch[i].debug = debug;
		hw->bch[i].debug = debug;
		mISDN_initbchannel(&hw->bch[i], MAX_DATA_MEM);
		mISDN_initbchannel(&hw->bch[i], MAX_DATA_MEM, poll >> 1);
		hw->bch[i].hw = hw;
		hw->bch[i].hw = hw;
		hw->bch[i].ch.send = hfcusb_l2l1B;
		hw->bch[i].ch.send = hfcusb_l2l1B;
		hw->bch[i].ch.ctrl = hfc_bctrl;
		hw->bch[i].ch.ctrl = hfc_bctrl;
+6 −21
Original line number Original line Diff line number Diff line
@@ -1063,7 +1063,7 @@ ipac_rme(struct hscx_hw *hx)
		skb_trim(hx->bch.rx_skb, 0);
		skb_trim(hx->bch.rx_skb, 0);
	} else {
	} else {
		skb_trim(hx->bch.rx_skb, hx->bch.rx_skb->len - 1);
		skb_trim(hx->bch.rx_skb, hx->bch.rx_skb->len - 1);
		recv_Bchannel(&hx->bch, 0);
		recv_Bchannel(&hx->bch, 0, false);
	}
	}
}
}


@@ -1114,11 +1114,8 @@ ipac_irq(struct hscx_hw *hx, u8 ista)


	if (istab & IPACX_B_RPF) {
	if (istab & IPACX_B_RPF) {
		hscx_empty_fifo(hx, hx->fifo_size);
		hscx_empty_fifo(hx, hx->fifo_size);
		if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags)) {
		if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags))
			/* receive transparent audio data */
			recv_Bchannel(&hx->bch, 0, false);
			if (hx->bch.rx_skb)
				recv_Bchannel(&hx->bch, 0);
		}
	}
	}


	if (istab & IPACX_B_RFO) {
	if (istab & IPACX_B_RFO) {
@@ -1377,20 +1374,7 @@ hscx_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
static int
static int
channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
{
{
	int	ret = 0;
	return mISDN_ctrl_bchannel(bch, cq);

	switch (cq->op) {
	case MISDN_CTRL_GETOP:
		cq->op = 0;
		break;
		/* Nothing implemented yet */
	case MISDN_CTRL_FILL_EMPTY:
	default:
		pr_info("%s: unknown Op %x\n", __func__, cq->op);
		ret = -EINVAL;
		break;
	}
	return ret;
}
}


static int
static int
@@ -1608,7 +1592,8 @@ mISDNipac_init(struct ipac_hw *ipac, void *hw)
		set_channelmap(i + 1, ipac->isac.dch.dev.channelmap);
		set_channelmap(i + 1, ipac->isac.dch.dev.channelmap);
		list_add(&ipac->hscx[i].bch.ch.list,
		list_add(&ipac->hscx[i].bch.ch.list,
			 &ipac->isac.dch.dev.bchannels);
			 &ipac->isac.dch.dev.bchannels);
		mISDN_initbchannel(&ipac->hscx[i].bch, MAX_DATA_MEM);
		mISDN_initbchannel(&ipac->hscx[i].bch, MAX_DATA_MEM,
				   ipac->hscx[i].fifo_size);
		ipac->hscx[i].bch.ch.nr = i + 1;
		ipac->hscx[i].bch.ch.nr = i + 1;
		ipac->hscx[i].bch.ch.send = &hscx_l2l1;
		ipac->hscx[i].bch.ch.send = &hscx_l2l1;
		ipac->hscx[i].bch.ch.ctrl = hscx_bctrl;
		ipac->hscx[i].bch.ch.ctrl = hscx_bctrl;
Loading