summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2008-07-09 21:27:07 +0000
committerShaun Ruffell <sruffell@digium.com>2008-07-09 21:27:07 +0000
commite08995ee066063a3db960046bc5b6c0543db0444 (patch)
treeb443b0f1d59c3d24db6186938ffc042dbf6d4c06
parent567a9becaa5e865726c9185c2eabfc14d902dc97 (diff)
Saving off some work in progress on half-full buffering. Still needs a method
for dumping half the buffer on tx overrun from the user side. Also, the behavior of half-full on the rx side has not been checked. git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@4589 a0bf4364-ded3-4de4-8d8a-66a801d63aff
-rw-r--r--drivers/dahdi/dahdi-base.c139
-rw-r--r--include/dahdi/kernel.h7
2 files changed, 111 insertions, 35 deletions
diff --git a/drivers/dahdi/dahdi-base.c b/drivers/dahdi/dahdi-base.c
index 5f9de80..e69b2fb 100644
--- a/drivers/dahdi/dahdi-base.c
+++ b/drivers/dahdi/dahdi-base.c
@@ -850,15 +850,17 @@ static int dahdi_reallocbufs(struct dahdi_chan *ss, int j, int numbufs)
ss->outreadbuf = -1;
ss->outwritebuf = -1;
ss->numbufs = numbufs;
- if (ss->txbufpolicy == DAHDI_POLICY_WHEN_FULL)
+ if (DAHDI_POLICY_IMMEDIATE != ss->txbufpolicy) {
ss->txdisable = 1;
- else
+ } else {
ss->txdisable = 0;
+ }
- if (ss->rxbufpolicy == DAHDI_POLICY_WHEN_FULL)
+ if (DAHDI_POLICY_IMMEDIATE != ss->rxbufpolicy) {
ss->rxdisable = 1;
- else
+ } else {
ss->rxdisable = 0;
+ }
spin_unlock_irqrestore(&ss->lock, flags);
if (oldbuf)
@@ -1448,8 +1450,8 @@ static int dahdi_net_open(hdlc_device *hdlc)
module_printk(KERN_NOTICE, "%s is not a net device!\n", ms->name);
return -EINVAL;
}
- ms->txbufpolicy = DAHDI_POLICY_IMMEDIATE;
- ms->rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
+ ms->txbufpolicy = DAHDI_POLICY_DEFAULT;
+ ms->rxbufpolicy = DAHDI_POLICY_DEFAULT;
res = dahdi_reallocbufs(ms, DAHDI_DEFAULT_MTU_MRU, DAHDI_DEFAULT_NUM_BUFS);
if (res)
@@ -1894,8 +1896,9 @@ static ssize_t dahdi_chan_read(struct file *file, char *usrbuf, size_t count, in
if (chan->outreadbuf == chan->inreadbuf) {
/* Out of stuff */
chan->outreadbuf = -1;
- if (chan->rxbufpolicy == DAHDI_POLICY_WHEN_FULL)
+ if (DAHDI_POLICY_IMMEDIATE != chan->rxbufpolicy) {
chan->rxdisable = 1;
+ }
}
if (chan->inreadbuf < 0) {
/* Notify interrupt handler that we have some space now */
@@ -1906,6 +1909,35 @@ static ssize_t dahdi_chan_read(struct file *file, char *usrbuf, size_t count, in
return amnt;
}
+static int __attribute__((const)) buffers_half_full(int hp, int tp, int length)
+{
+ if (hp < 0) {
+ /* We're full... */
+ return 1;
+ }
+ if (tp < 0) {
+ /* We're empty ... */
+ return 0;
+ }
+ if (hp > tp) {
+ return ((hp - tp) > length / 2) ? 1 : 0;
+ } else {
+ return (((length - tp) + hp) > length/2 ) ? 1 : 0;
+ }
+}
+
+static int tx_buffers_half_full(struct dahdi_chan *chan)
+{
+ return buffers_half_full(chan->inwritebuf, chan->outwritebuf,
+ chan->numbufs);
+}
+
+static int rx_buffers_half_full(struct dahdi_chan *chan)
+{
+ return buffers_half_full(chan->inreadbuf, chan->outreadbuf,
+ chan->numbufs);
+}
+
static ssize_t dahdi_chan_write(struct file *file, const char *usrbuf, size_t count, int unit)
{
unsigned long flags;
@@ -1934,7 +1966,14 @@ 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 (DAHDI_POLICY_HALF_FULL == chan->txbufpolicy) {
+ if (chan->flags & DAHDI_FLAG_AUDIO) {
+ /* dahdi_flush_half_tx_buffers(chan); */
+ ;
+ }
+ }
+ if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
/* Wait for something to be available */
rv = schluffen(&chan->writebufq);
@@ -2002,6 +2041,14 @@ static ssize_t dahdi_chan_write(struct file *file, const char *usrbuf, size_t co
chan->inwritebuf = -1;
/* Make sure the transmitter is transmitting in case of POLICY_WHEN_FULL */
chan->txdisable = 0;
+ } else if (chan->txdisable) {
+ /* We might need to enable the transmitter again if the
+ * policy is set to half full. */
+ if (DAHDI_POLICY_HALF_FULL == chan->txbufpolicy) {
+ if (tx_buffers_half_full(chan)) {
+ chan->txdisable = 0;
+ }
+ }
}
if (chan->outwritebuf < 0) {
/* Okay, the interrupt handler has been waiting for us. Give them a buffer */
@@ -2242,8 +2289,8 @@ static int initialize_channel(struct dahdi_chan *chan)
spin_lock_irqsave(&chan->lock, flags);
- chan->rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
- chan->txbufpolicy = DAHDI_POLICY_IMMEDIATE;
+ chan->rxbufpolicy = DAHDI_POLICY_DEFAULT;
+ chan->txbufpolicy = DAHDI_POLICY_DEFAULT;
ec_state = chan->ec_state;
chan->ec_state = NULL;
@@ -4101,6 +4148,29 @@ static int ioctl_dahdi_dial(struct dahdi_chan *chan, unsigned long data)
return rv;
}
+static void dahdi_flush_tx_buffers(struct dahdi_chan *chan)
+{
+ int j;
+ /* initialize write buffers and pointers */
+ chan->outwritebuf = -1;
+ chan->inwritebuf = 0;
+ for (j=0;j<chan->numbufs;j++) {
+ /* Do we need this? */
+ chan->writen[j] = 0;
+ chan->writeidx[j] = 0;
+ }
+ wake_up_interruptible(&chan->writebufq); /* wake_up_interruptible waiting on write */
+ wake_up_interruptible(&chan->sel); /* wake_up_interruptible waiting on select */
+ /* if IO MUX wait on write empty, well, this
+ certainly *did* empty the write */
+ if (chan->iomask & DAHDI_IOMUX_WRITEEMPTY)
+ wake_up_interruptible(&chan->eventbufq); /* wake_up_interruptible waiting on IOMUX */
+
+ if (DAHDI_POLICY_IMMEDIATE != chan->txbufpolicy) {
+ chan->txdisable = 1;
+ }
+}
+
static int dahdi_chanandpseudo_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data, int unit)
{
struct dahdi_chan *chan = chans[unit];
@@ -4145,8 +4215,11 @@ static int dahdi_chanandpseudo_ioctl(struct inode *inode, struct file *file, uns
return -EINVAL;
if (stack.bi.bufsize * stack.bi.numbufs > DAHDI_MAX_BUF_SPACE)
return -EINVAL;
- chan->rxbufpolicy = stack.bi.rxbufpolicy & 0x1;
- chan->txbufpolicy = stack.bi.txbufpolicy & 0x1;
+ /* TODO: Change mask to inline function to validate the policy. */
+ chan->rxbufpolicy = stack.bi.rxbufpolicy & 0x3;
+ chan->txbufpolicy = stack.bi.txbufpolicy & 0x3;
+ /* !!!SRR!!! */
+ printk(KERN_DEBUG "txpolicy: %d rxpolicy: %d\n", chan->txbufpolicy, chan->rxbufpolicy);
if ((rv = dahdi_reallocbufs(chan, stack.bi.bufsize, stack.bi.numbufs)))
return (rv);
break;
@@ -4179,24 +4252,14 @@ static int dahdi_chanandpseudo_ioctl(struct inode *inode, struct file *file, uns
}
wake_up_interruptible(&chan->readbufq); /* wake_up_interruptible waiting on read */
wake_up_interruptible(&chan->sel); /* wake_up_interruptible waiting on select */
- }
- if (i & DAHDI_FLUSH_WRITE) /* if for write (output) */
- {
- /* initialize write buffers and pointers */
- chan->outwritebuf = -1;
- chan->inwritebuf = 0;
- for (j=0;j<chan->numbufs;j++) {
- /* Do we need this? */
- chan->writen[j] = 0;
- chan->writeidx[j] = 0;
+
+ if (DAHDI_POLICY_IMMEDIATE != chan->rxbufpolicy) {
+ chan->txdisable = 1;
}
- wake_up_interruptible(&chan->writebufq); /* wake_up_interruptible waiting on write */
- wake_up_interruptible(&chan->sel); /* wake_up_interruptible waiting on select */
- /* if IO MUX wait on write empty, well, this
- certainly *did* empty the write */
- if (chan->iomask & DAHDI_IOMUX_WRITEEMPTY)
- wake_up_interruptible(&chan->eventbufq); /* wake_up_interruptible waiting on IOMUX */
}
+ if (i & DAHDI_FLUSH_WRITE) { /* if for write (output) */
+ dahdi_flush_tx_buffers(chan);
+ }
if (i & DAHDI_FLUSH_EVENT) /* if for events */
{
/* initialize the event pointers */
@@ -5753,18 +5816,20 @@ static inline void __dahdi_getbuf_chunk(struct dahdi_chan *ss, unsigned char *tx
ms->outwritebuf = -1;
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 we're only supposed to start when not empty, disable the transmitter */
+ if (DAHDI_POLICY_IMMEDIATE != ms->txbufpolicy) {
ms->txdisable = 1;
+ }
}
} else {
if (ms->outwritebuf == ms->inwritebuf) {
ms->outwritebuf = oldbuf;
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 we're only supposed to start when not empty, disable the transmitter */
+ if (DAHDI_POLICY_IMMEDIATE != ms->txbufpolicy) {
ms->txdisable = 1;
+ }
}
}
if (ms->inwritebuf < 0) {
@@ -6827,7 +6892,14 @@ static inline void __putbuf_chunk(struct dahdi_chan *ss, unsigned char *rxb, int
ms->inreadbuf = -1;
/* Enable the receiver in case they've got POLICY_WHEN_FULL */
ms->rxdisable = 0;
+ } else if (ms->rxdisable) {
+ if (DAHDI_POLICY_HALF_FULL == ms->rxbufpolicy) {
+ if (rx_buffers_half_full(ms)) {
+ ms->rxdisable = 0;
+ }
+ }
}
+
if (ms->outreadbuf < 0) { /* start out buffer if not already */
ms->outreadbuf = oldbuf;
}
@@ -7066,8 +7138,9 @@ extern int dahdi_hdlc_getbuf(struct dahdi_chan *ss, unsigned char *bufptr, unsig
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 (DAHDI_POLICY_IMMEDIATE != ss->txbufpolicy) {
ss->txdisable = 1;
+ }
res = -1;
}
diff --git a/include/dahdi/kernel.h b/include/dahdi/kernel.h
index b2ac0ff..d76ab32 100644
--- a/include/dahdi/kernel.h
+++ b/include/dahdi/kernel.h
@@ -157,8 +157,11 @@
#define DAHDI_DEFAULT_BLOCKSIZE 1024
#define DAHDI_DEFAULT_MTR_MRU 2048
-#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_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 /* ...and when buffer is half full. */
+
+#define DAHDI_POLICY_DEFAULT DAHDI_POLICY_HALF_FULL
#define RING_DEBOUNCE_TIME 2000 /* 2000 ms ring debounce time */