diff options
author | Matthew Fredrickson <creslin@digium.com> | 2008-12-19 21:14:00 +0000 |
---|---|---|
committer | Matthew Fredrickson <creslin@digium.com> | 2008-12-19 21:14:00 +0000 |
commit | dda189e53d42ea8e1cc6396eeefdb95f67eb759a (patch) | |
tree | 63b892e59814ac5e38e5827f0eb983370574ecb2 | |
parent | 34860cc9bf9af24623341dd51e3bcbbf0486815b (diff) |
Add support for new half full buffer policy. This significantly improves performance in fax and data modem calls.
git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@5597 a0bf4364-ded3-4de4-8d8a-66a801d63aff
-rw-r--r-- | drivers/dahdi/dahdi-base.c | 78 | ||||
-rw-r--r-- | include/dahdi/kernel.h | 4 | ||||
-rw-r--r-- | include/dahdi/user.h | 4 |
3 files changed, 74 insertions, 12 deletions
diff --git a/drivers/dahdi/dahdi-base.c b/drivers/dahdi/dahdi-base.c index e54e35e..fefe98a 100644 --- a/drivers/dahdi/dahdi-base.c +++ b/drivers/dahdi/dahdi-base.c @@ -940,7 +940,7 @@ static int dahdi_reallocbufs(struct dahdi_chan *ss, int j, int numbufs) ss->outwritebuf = -1; ss->numbufs = numbufs; - if (ss->txbufpolicy == DAHDI_POLICY_WHEN_FULL) + if ((ss->txbufpolicy == DAHDI_POLICY_WHEN_FULL) || (ss->txbufpolicy == DAHDI_POLICY_HALF_FULL)) ss->txdisable = 1; else ss->txdisable = 0; @@ -2022,6 +2022,29 @@ static ssize_t dahdi_chan_read(struct file *file, char *usrbuf, size_t count, in return amnt; } +static int num_filled_bufs(struct dahdi_chan *chan) +{ + int range1, range2; + + if (chan->inwritebuf < 0) { + return chan->numbufs; + } + + if (chan->outwritebuf < 0) { + return 0; + } + + if (chan->outwritebuf <= chan->inwritebuf) { + return chan->inwritebuf - chan->outwritebuf; + } + + /* This means (in > out) and we have wrap around */ + range1 = chan->numbufs - chan->outwritebuf; + range2 = chan->inwritebuf; + + return range1 + range2; +} + static ssize_t dahdi_chan_write(struct file *file, const char *usrbuf, size_t count, int unit) { unsigned long flags; @@ -2034,8 +2057,9 @@ static ssize_t dahdi_chan_write(struct file *file, const char *usrbuf, size_t co if (!chan) return -EINVAL; - if (count < 1) + if (count < 1) { return -EINVAL; + } for (;;) { spin_lock_irqsave(&chan->lock, flags); @@ -2054,12 +2078,17 @@ static ssize_t dahdi_chan_write(struct file *file, const char *usrbuf, size_t co spin_unlock_irqrestore(&chan->lock, flags); if (res >= 0) break; - if (file->f_flags & O_NONBLOCK) + if (file->f_flags & O_NONBLOCK) { +#ifdef BUFFER_DEBUG + printk("Error: Nonblock\n"); +#endif return -EAGAIN; + } /* Wait for something to be available */ rv = schluffen(&chan->writebufq); - if (rv) + if (rv) { return rv; + } } amnt = count; @@ -2097,8 +2126,9 @@ static ssize_t dahdi_chan_write(struct file *file, const char *usrbuf, size_t co pass = left; if (pass > 128) pass = 128; - if (copy_from_user(lindata, usrbuf + (pos << 1), pass << 1)) + if (copy_from_user(lindata, usrbuf + (pos << 1), pass << 1)) { return -EFAULT; + } left -= pass; for (x = 0; x < pass; x++) chan->writebuf[res][x + pos] = DAHDI_LIN2X(lindata[x], chan); @@ -2106,8 +2136,9 @@ static ssize_t dahdi_chan_write(struct file *file, const char *usrbuf, size_t co } chan->writen[res] = amnt >> 1; } else { - if (copy_from_user(chan->writebuf[res], usrbuf, amnt)) + if (copy_from_user(chan->writebuf[res], usrbuf, amnt)) { return -EFAULT; + } chan->writen[res] = amnt; } chan->writeidx[res] = 0; @@ -2116,6 +2147,7 @@ static ssize_t dahdi_chan_write(struct file *file, const char *usrbuf, size_t co oldbuf = res; spin_lock_irqsave(&chan->lock, flags); chan->inwritebuf = (res + 1) % chan->numbufs; + if (chan->inwritebuf == chan->outwritebuf) { /* Don't stomp on the transmitter, just wait for them to wake us up */ @@ -2123,10 +2155,29 @@ static ssize_t dahdi_chan_write(struct file *file, const char *usrbuf, size_t co /* Make sure the transmitter is transmitting in case of POLICY_WHEN_FULL */ chan->txdisable = 0; } + if (chan->outwritebuf < 0) { /* Okay, the interrupt handler has been waiting for us. Give them a buffer */ chan->outwritebuf = oldbuf; } + + if ((chan->txbufpolicy == DAHDI_POLICY_HALF_FULL) && (chan->txdisable)) { + if (num_filled_bufs(chan) >= (chan->numbufs >> 1)) { +#ifdef BUFFER_DEBUG + printk("Reached buffer fill mark of %d\n", num_filled_bufs(chan)); +#endif + chan->txdisable = 0; + } + } + +#ifdef BUFFER_DEBUG + if ((chan->statcount <= 0) || (amnt != 128) || (num_filled_bufs(chan) != chan->lastnumbufs)) { + printk("amnt: %d Number of filled buffers: %d\n", amnt, num_filled_bufs(chan)); + chan->statcount = 32000; + chan->lastnumbufs = num_filled_bufs(chan); + } +#endif + spin_unlock_irqrestore(&chan->lock, flags); if (chan->flags & DAHDI_FLAG_NOSTDTXRX && chan->span->hdlc_hard_xmit) @@ -4306,7 +4357,7 @@ static int dahdi_chanandpseudo_ioctl(struct inode *inode, struct file *file, uns * different since we might want to allow the kernel to build * up a buffer in order to prevent underruns from the * interrupt context. */ - chan->txbufpolicy = stack.bi.txbufpolicy & 0x1; + chan->txbufpolicy = stack.bi.txbufpolicy & 0x3; if ((rv = dahdi_reallocbufs(chan, stack.bi.bufsize, stack.bi.numbufs))) return (rv); break; @@ -5956,7 +6007,8 @@ static inline void __dahdi_getbuf_chunk(struct dahdi_chan *ss, unsigned char *tx if (ms->iomask & (DAHDI_IOMUX_WRITE | DAHDI_IOMUX_WRITEEMPTY)) wake_up_interruptible(&ms->eventbufq); /* If we're only supposed to start when full, disable the transmitter */ - if (ms->txbufpolicy == DAHDI_POLICY_WHEN_FULL) + if ((ms->txbufpolicy == DAHDI_POLICY_WHEN_FULL) || + (ms->txbufpolicy == DAHDI_POLICY_HALF_FULL)) ms->txdisable = 1; } } else { @@ -5965,7 +6017,8 @@ static inline void __dahdi_getbuf_chunk(struct dahdi_chan *ss, unsigned char *tx if (ms->iomask & (DAHDI_IOMUX_WRITE | DAHDI_IOMUX_WRITEEMPTY)) wake_up_interruptible(&ms->eventbufq); /* If we're only supposed to start when full, disable the transmitter */ - if (ms->txbufpolicy == DAHDI_POLICY_WHEN_FULL) + if ((ms->txbufpolicy == DAHDI_POLICY_WHEN_FULL) || + (ms->txbufpolicy == DAHDI_POLICY_HALF_FULL)) ms->txdisable = 1; } } @@ -7023,7 +7076,7 @@ static inline void __putbuf_chunk(struct dahdi_chan *ss, unsigned char *rxb, int /* Whoops, we're full, and have no where else to store into at the moment. We'll drop it until there's a buffer available */ -#ifdef CONFIG_DAHDI_DEBUG +#ifdef BUFFER_DEBUG module_printk(KERN_NOTICE, "Out of storage space\n"); #endif ms->inreadbuf = -1; @@ -7275,7 +7328,7 @@ int dahdi_hdlc_getbuf(struct dahdi_chan *ss, unsigned char *bufptr, unsigned int if (ss->iomask & (DAHDI_IOMUX_WRITE | DAHDI_IOMUX_WRITEEMPTY)) wake_up_interruptible(&ss->eventbufq); /* If we're only supposed to start when full, disable the transmitter */ - if (ss->txbufpolicy == DAHDI_POLICY_WHEN_FULL) + if ((ss->txbufpolicy == DAHDI_POLICY_WHEN_FULL) || (ss->txbufpolicy == DAHDI_POLICY_HALF_FULL)) ss->txdisable = 1; res = -1; } @@ -7681,6 +7734,9 @@ int dahdi_receive(struct dahdi_span *span) } } } +#ifdef BUFFER_DEBUG + span->chans[x]->statcount -= DAHDI_CHUNKSIZE; +#endif spin_unlock_irqrestore(&span->chans[x]->lock, flags); } } diff --git a/include/dahdi/kernel.h b/include/dahdi/kernel.h index 738cb0f..47139e5 100644 --- a/include/dahdi/kernel.h +++ b/include/dahdi/kernel.h @@ -139,6 +139,10 @@ struct dahdi_chan { int do_ppp_error; struct sk_buff_head ppp_rq; #endif +#ifdef BUFFER_DEBUG + int statcount; + int lastnumbufs; +#endif spinlock_t lock; char name[40]; /* Specified by DAHDI */ diff --git a/include/dahdi/user.h b/include/dahdi/user.h index ff86589..2e4615e 100644 --- a/include/dahdi/user.h +++ b/include/dahdi/user.h @@ -110,7 +110,7 @@ #define DAHDI_MAX_BLOCKSIZE 8192 #define DAHDI_DEFAULT_NUM_BUFS 2 -#define DAHDI_MAX_NUM_BUFS 32 +#define DAHDI_MAX_NUM_BUFS 128 #define DAHDI_MAX_BUF_SPACE 32768 #define DAHDI_DEFAULT_BLOCKSIZE 1024 @@ -118,6 +118,8 @@ #define DAHDI_POLICY_IMMEDIATE 0 /* Start play/record immediately */ #define DAHDI_POLICY_WHEN_FULL 1 /* Start play/record when buffer is full */ +#define DAHDI_POLICY_HALF_FULL 2 /* Start play/record when buffer is half full. + Note -- This policy only works on tx buffers */ #define DAHDI_GET_PARAMS_RETURN_MASTER 0x40000000 |