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

Commit 87c5fa1b authored by Andreas Eversberg's avatar Andreas Eversberg Committed by Karsten Keil
Browse files

mISDN: Add different different timer settings for hfc-pci



     - Poll-timer can now be set from 8 to 256 samples, depending on your kernel.
     - If default or 128 is used, the normal controller's clock is used as before.
       Usage: modprobe hfcpci poll=XXX
     - Added some debug code for dsp buffer size. (CMX_DELAY_DEBUG)

    Signed-off-by: default avatarAndreas Eversberg <andreas@eversberg.eu>
    Signed-off-by: default avatarKarsten Keil <kkeil@suse.de>
parent 1b36c78f
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@
 * change mask and threshold simultaneously
 */
#define HFCPCI_BTRANS_THRESHOLD 128
#define HFCPCI_BTRANS_MAX	256
#define HFCPCI_FILLEMPTY	64
#define HFCPCI_BTRANS_THRESMASK 0x00

+125 −27
Original line number Diff line number Diff line
@@ -23,6 +23,25 @@
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * Module options:
 *
 * debug:
 *	NOTE: only one poll value must be given for all cards
 *	See hfc_pci.h for debug flags.
 *
 * poll:
 *	NOTE: only one poll value must be given for all cards
 *	Give the number of samples for each fifo process.
 *	By default 128 is used. Decrease to reduce delay, increase to
 *	reduce cpu load. If unsure, don't mess with it!
 *	A value of 128 will use controller's interrupt. Other values will
 *	use kernel timer, because the controller will not allow lower values
 *	than 128.
 *	Also note that the value depends on the kernel timer frequency.
 *	If kernel uses a frequency of 1000 Hz, steps of 8 samples are possible.
 *	If the kernel uses 100 Hz, steps of 80 samples are possible.
 *	If the kernel uses 300 Hz, steps of about 26 samples are possible.
 *
 */

#include <linux/module.h>
@@ -36,10 +55,14 @@ static const char *hfcpci_revision = "2.0";

static int HFC_cnt;
static uint debug;
static uint poll, tics;
struct timer_list hfc_tl;
u32	hfc_jiffies;

MODULE_AUTHOR("Karsten Keil");
MODULE_LICENSE("GPL");
module_param(debug, uint, 0);
module_param(poll, uint, S_IRUGO | S_IWUSR);

static LIST_HEAD(HFClist);
static DEFINE_RWLOCK(HFClock);
@@ -519,9 +542,9 @@ receive_dmsg(struct hfc_pci *hc)
}

/*
 * check for transparent receive data and read max one threshold size if avail
 * check for transparent receive data and read max one 'poll' size if avail
 */
static int
static void
hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *bz, u_char *bdata)
{
	 __le16 *z1r, *z2r;
@@ -533,17 +556,19 @@ hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *bz, u_char *bdata)

	fcnt = le16_to_cpu(*z1r) - le16_to_cpu(*z2r);
	if (!fcnt)
		return 0;	/* no data avail */
		return;	/* no data avail */

	if (fcnt <= 0)
		fcnt += B_FIFO_SIZE;	/* bytes actually buffered */
	if (fcnt > HFCPCI_BTRANS_THRESHOLD)
		fcnt = HFCPCI_BTRANS_THRESHOLD;		/* limit size */

	new_z2 = le16_to_cpu(*z2r) + fcnt;	/* new position in fifo */
	if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
		new_z2 -= B_FIFO_SIZE;	/* buffer wrap */

	if (fcnt > MAX_DATA_SIZE) {	/* flush, if oversized */
		*z2r = cpu_to_le16(new_z2);		/* new position */
		return;
	}

	bch->rx_skb = mI_alloc_skb(fcnt, GFP_ATOMIC);
	if (bch->rx_skb) {
		ptr = skb_put(bch->rx_skb, fcnt);
@@ -568,7 +593,6 @@ hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *bz, u_char *bdata)
		printk(KERN_WARNING "HFCPCI: receive out of memory\n");

	*z2r = cpu_to_le16(new_z2);		/* new position */
	return 1;
}

/*
@@ -579,12 +603,11 @@ main_rec_hfcpci(struct bchannel *bch)
{
	struct hfc_pci	*hc = bch->hw;
	int		rcnt, real_fifo;
	int		receive, count = 5;
	int		receive = 0, count = 5;
	struct bzfifo	*bz;
	u_char		*bdata;
	struct zt	*zp;


	if ((bch->nr & 2) && (!hc->hw.bswapped)) {
		bz = &((union fifo_area *)(hc->hw.fifos))->b_chans.rxbz_b2;
		bdata = ((union fifo_area *)(hc->hw.fifos))->b_chans.rxdat_b2;
@@ -624,9 +647,10 @@ main_rec_hfcpci(struct bchannel *bch)
			receive = 1;
		else
			receive = 0;
	} else if (test_bit(FLG_TRANSPARENT, &bch->Flags))
		receive = hfcpci_empty_fifo_trans(bch, bz, bdata);
	else
	} else if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {
		hfcpci_empty_fifo_trans(bch, bz, bdata);
		return;
	} else
		receive = 0;
	if (count && receive)
		goto Begin;
@@ -782,9 +806,9 @@ hfcpci_fill_fifo(struct bchannel *bch)

next_t_frame:
		count = bch->tx_skb->len - bch->tx_idx;
		/* maximum fill shall be HFCPCI_BTRANS_MAX */
		if (count > HFCPCI_BTRANS_MAX - fcnt)
			count = HFCPCI_BTRANS_MAX - fcnt;
		/* maximum fill shall be poll*2 */
		if (count > (poll << 1) - fcnt)
			count = (poll << 1) - fcnt;
		if (count <= 0)
			return;
		/* data is suitable for fifo */
@@ -1164,37 +1188,37 @@ hfcpci_int(int intno, void *dev_id)
		val &= ~0x80;
		Write_hfc(hc, HFCPCI_CTMT, hc->hw.ctmt | HFCPCI_CLTIMER);
	}
	if (val & 0x08) {
	if (val & 0x08) { 	/* B1 rx */
		bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1);
		if (bch)
			main_rec_hfcpci(bch);
		else if (hc->dch.debug)
			printk(KERN_DEBUG "hfcpci spurious 0x08 IRQ\n");
	}
	if (val & 0x10) {
	if (val & 0x10) {	/* B2 rx */
		bch = Sel_BCS(hc, 2);
		if (bch)
			main_rec_hfcpci(bch);
		else if (hc->dch.debug)
			printk(KERN_DEBUG "hfcpci spurious 0x10 IRQ\n");
	}
	if (val & 0x01) {
	if (val & 0x01) {	/* B1 tx */
		bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1);
		if (bch)
			tx_birq(bch);
		else if (hc->dch.debug)
			printk(KERN_DEBUG "hfcpci spurious 0x01 IRQ\n");
	}
	if (val & 0x02) {
	if (val & 0x02) {	/* B2 tx */
		bch = Sel_BCS(hc, 2);
		if (bch)
			tx_birq(bch);
		else if (hc->dch.debug)
			printk(KERN_DEBUG "hfcpci spurious 0x02 IRQ\n");
	}
	if (val & 0x20)
	if (val & 0x20)		/* D rx */
		receive_dmsg(hc);
	if (val & 0x04) {	/* dframe transmitted */
	if (val & 0x04) {	/* D tx */
		if (test_and_clear_bit(FLG_BUSY_TIMER, &hc->dch.Flags))
			del_timer(&hc->dch.timer);
		tx_dirq(&hc->dch);
@@ -1203,6 +1227,41 @@ hfcpci_int(int intno, void *dev_id)
	return IRQ_HANDLED;
}

static void
hfcpci_softirq(void *arg)
{
	u_long		flags;
	struct bchannel	*bch;
	struct hfc_pci	*hc;

	write_lock_irqsave(&HFClock, flags);
	list_for_each_entry(hc, &HFClist, list) {
		if (hc->hw.int_m2 & HFCPCI_IRQ_ENABLE) {
			spin_lock(&hc->lock);
			bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1);
			if (bch && bch->state == ISDN_P_B_RAW) { /* B1 rx&tx */
				main_rec_hfcpci(bch);
				tx_birq(bch);
			}
			bch = Sel_BCS(hc, hc->hw.bswapped ? 1 : 2);
			if (bch && bch->state == ISDN_P_B_RAW) { /* B2 rx&tx */
				main_rec_hfcpci(bch);
				tx_birq(bch);
			}
			spin_unlock(&hc->lock);
		}
	}
	write_unlock_irqrestore(&HFClock, flags);

	/* if next event would be in the past ... */
	if ((s32)(hfc_jiffies + tics - jiffies) <= 0)
		hfc_jiffies = jiffies + 1;
	else
		hfc_jiffies += tics;
	hfc_tl.expires = hfc_jiffies;
	add_timer(&hfc_tl);
}

/*
 * timer callback for D-chan busy resolution. Currently no function
 */
@@ -1312,12 +1371,14 @@ mode_hfcpci(struct bchannel *bch, int bc, int protocol)
		}
		if (fifo2 & 2) {
			hc->hw.fifo_en |= HFCPCI_FIFOEN_B2;
			if (!tics)
				hc->hw.int_m1 |= (HFCPCI_INTS_B2TRANS +
				    HFCPCI_INTS_B2REC);
			hc->hw.ctmt |= 2;
			hc->hw.conn &= ~0x18;
		} else {
			hc->hw.fifo_en |= HFCPCI_FIFOEN_B1;
			if (!tics)
				hc->hw.int_m1 |= (HFCPCI_INTS_B1TRANS +
				    HFCPCI_INTS_B1REC);
			hc->hw.ctmt |= 1;
@@ -1427,6 +1488,7 @@ set_hfcpci_rxtest(struct bchannel *bch, int protocol, int chan)
		if (chan & 2) {
			hc->hw.sctrl_r |= SCTRL_B2_ENA;
			hc->hw.fifo_en |= HFCPCI_FIFOEN_B2RX;
			if (!tics)
				hc->hw.int_m1 |= HFCPCI_INTS_B2REC;
			hc->hw.ctmt |= 2;
			hc->hw.conn &= ~0x18;
@@ -1436,6 +1498,7 @@ set_hfcpci_rxtest(struct bchannel *bch, int protocol, int chan)
		} else {
			hc->hw.sctrl_r |= SCTRL_B1_ENA;
			hc->hw.fifo_en |= HFCPCI_FIFOEN_B1RX;
			if (!tics)
				hc->hw.int_m1 |= HFCPCI_INTS_B1REC;
			hc->hw.ctmt |= 1;
			hc->hw.conn &= ~0x03;
@@ -2273,7 +2336,39 @@ HFC_init(void)
{
	int		err;

	if (!poll)
		poll = HFCPCI_BTRANS_THRESHOLD;

	if (poll != HFCPCI_BTRANS_THRESHOLD) {
		tics = poll * HZ / 8000;
		if (tics < 1)
			tics = 1;
		poll = tics * 8000 / HZ;
		if (poll > 256 || poll < 8) {
			printk(KERN_ERR "%s: Wrong poll value %d not in range "
				"of 8..256.\n", __func__, poll);
			err = -EINVAL;
			return err;
		}
	}
	if (poll != HFCPCI_BTRANS_THRESHOLD) {
		printk(KERN_INFO "%s: Using alternative poll value of %d\n",
			__func__, poll);
		hfc_tl.function = (void *)hfcpci_softirq;
		hfc_tl.data = 0;
		init_timer(&hfc_tl);
		hfc_tl.expires = jiffies + tics;
		hfc_jiffies = hfc_tl.expires;
		add_timer(&hfc_tl);
	} else
		tics = 0; /* indicate the use of controller's timer */

	err = pci_register_driver(&hfc_driver);
	if (err) {
		if (timer_pending(&hfc_tl))
			del_timer(&hfc_tl);
	}

	return err;
}

@@ -2282,6 +2377,9 @@ HFC_cleanup(void)
{
	struct hfc_pci	*card, *next;

	if (timer_pending(&hfc_tl))
		del_timer(&hfc_tl);

	list_for_each_entry_safe(card, next, &HFClist, list) {
		release_card(card);
	}
+23 −0
Original line number Diff line number Diff line
@@ -137,6 +137,7 @@
/* #define CMX_CONF_DEBUG */

/*#define CMX_DEBUG * massive read/write pointer output */
/*#define CMX_DELAY_DEBUG * gives rx-buffer delay overview */
/*#define CMX_TX_DEBUG * massive read/write on tx-buffer with content */

static inline int
@@ -1135,6 +1136,25 @@ dsp_cmx_conf(struct dsp *dsp, u32 conf_id)
	return 0;
}

#ifdef CMX_DELAY_DEBUG
int delaycount;
static void
showdelay(struct dsp *dsp, int samples, int delay)
{
	char bar[] = "--------------------------------------------------|";
	int sdelay;

	delaycount += samples;
	if (delaycount < 8000)
		return;
	delaycount = 0;

	sdelay = delay * 50 / (dsp_poll << 2);

	printk(KERN_DEBUG "DELAY (%s) %3d >%s\n", dsp->name, delay,
		sdelay > 50 ? "..." : bar + 50 - sdelay);
}
#endif

/*
 * audio data is received from card
@@ -1256,6 +1276,9 @@ dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb)

	/* increase write-pointer */
	dsp->rx_W = ((dsp->rx_W+len) & CMX_BUFF_MASK);
#ifdef CMX_DELAY_DEBUG
	showdelay(dsp, len, (dsp->rx_W-dsp->rx_R) & CMX_BUFF_MASK);
#endif
}