summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2010-02-26 16:40:41 +0000
committerShaun Ruffell <sruffell@digium.com>2010-02-26 16:40:41 +0000
commit2f87293c69d2a4f9957c431646ec55c44675e217 (patch)
treebb8af0cbd063a8f1bc2aaa8c5c8bae4b8aae9a4c
parent2e9c5b03752de6db1cb54cc6da43d648c83165b6 (diff)
voicebus: Only use the slab debug facilities if CONFIG_SLAB_DEBUG is defined.
git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@8119 a0bf4364-ded3-4de4-8d8a-66a801d63aff
-rw-r--r--drivers/dahdi/voicebus/voicebus.c209
-rw-r--r--drivers/dahdi/voicebus/voicebus.h55
2 files changed, 162 insertions, 102 deletions
diff --git a/drivers/dahdi/voicebus/voicebus.c b/drivers/dahdi/voicebus/voicebus.c
index 93e54a9..eacc0f7 100644
--- a/drivers/dahdi/voicebus/voicebus.c
+++ b/drivers/dahdi/voicebus/voicebus.c
@@ -79,9 +79,12 @@
#define CSR7_AIE 0x00008000 /* abnormal enable */
#define CSR7_NIE 0x00010000 /* normal enable */
-#define DEFAULT_INTERRUPTS (CSR7_TCIE | CSR7_TPSIE | CSR7_TDUIE | \
- CSR7_RUIE | CSR7_RSIE | CSR7_FBEIE | \
- CSR7_AIE | CSR7_NIE)
+#define DEFAULT_COMMON_INTERRUPTS (CSR7_TCIE|CSR7_TPSIE|CSR7_RUIE|CSR7_RSIE|\
+ CSR7_FBEIE|CSR7_AIE|CSR7_NIE)
+
+#define DEFAULT_NORMAL_INTERRUPTS (DEFAULT_COMMON_INTERRUPTS|CSR7_TDUIE)
+
+#define DEFAULT_NO_IDLE_INTERRUPTS (DEFAULT_COMMON_INTERRUPTS|CSR7_RCIE)
#define CSR9 0x0048
#define CSR9_MDC 0x00010000
@@ -143,12 +146,6 @@ handle_receive(struct voicebus *vb, struct list_head *buffers)
#define VBUNLOCK_FROM_DEFERRED(_vb_) spin_lock(&((_vb_)->lock))
#endif
-/* Bit definitions for struct voicebus.flags */
-#define IN_DEFERRED_PROCESSING 1
-#define STOP 2
-#define STOPPED 3
-#define LATENCY_LOCKED 4
-
static inline struct voicebus_descriptor *
vb_descriptor(const struct voicebus_descriptor_list *dl,
const unsigned int index)
@@ -246,12 +243,12 @@ vb_initialize_tx_descriptors(struct voicebus *vb)
return -ENOMEM;
memset(dl->desc, 0, (sizeof(*d) + dl->padding) * DRING_SIZE);
+
for (i = 0; i < DRING_SIZE; ++i) {
d = vb_descriptor(dl, i);
d->des1 = des1;
- d->buffer1 = vb->idle_vbb_dma_addr;
- dl->pending[i] = vb->idle_vbb;
- SET_OWNED(d);
+ dl->pending[i] = NULL;
+ d->buffer1 = 0;
}
d->des1 |= cpu_to_le32(END_OF_RING);
atomic_set(&dl->count, 0);
@@ -306,35 +303,6 @@ voicebus_current_latency(struct voicebus *vb)
}
EXPORT_SYMBOL(voicebus_current_latency);
-/**
- * voicebus_lock_latency() - Do not increase the latency during underruns.
- *
- */
-void voicebus_lock_latency(struct voicebus *vb)
-{
- set_bit(LATENCY_LOCKED, &vb->flags);
-}
-EXPORT_SYMBOL(voicebus_lock_latency);
-
-/**
- * voicebus_unlock_latency() - Bump up the latency during underruns.
- *
- */
-void voicebus_unlock_latency(struct voicebus *vb)
-{
- clear_bit(LATENCY_LOCKED, &vb->flags);
-}
-EXPORT_SYMBOL(voicebus_unlock_latency);
-
-/**
- * voicebus_is_latency_locked() - Return 1 if latency is currently locked.
- *
- */
-int voicebus_is_latency_locked(const struct voicebus *vb)
-{
- return test_bit(LATENCY_LOCKED, &vb->flags);
-}
-EXPORT_SYMBOL(voicebus_is_latency_locked);
/*!
* \brief Read one of the hardware control registers without acquiring locks.
@@ -408,15 +376,21 @@ vb_cleanup_tx_descriptors(struct voicebus *vb)
VOICEBUS_SFRAME_SIZE, DMA_TO_DEVICE);
voicebus_free(vb, dl->pending[i]);
}
- d->des1 |= 0x80000000;
- d->buffer1 = vb->idle_vbb_dma_addr;
- dl->pending[i] = vb->idle_vbb;
- SET_OWNED(d);
+ if (!test_bit(VOICEBUS_NORMAL_MODE, &vb->flags)) {
+ d->buffer1 = 0;
+ dl->pending[i] = NULL;
+ d->des0 &= ~OWN_BIT;
+ } else {
+ d->des1 |= 0x80000000;
+ d->buffer1 = vb->idle_vbb_dma_addr;
+ dl->pending[i] = vb->idle_vbb;
+ SET_OWNED(d);
+ }
}
/* Send out two idle buffers to start because sometimes the first buffer
* doesn't make it back to us. */
- dl->head = dl->tail = 2;
+ dl->head = dl->tail = 0;
spin_unlock_irqrestore(&vb->lock, flags);
atomic_set(&dl->count, 0);
}
@@ -670,22 +644,25 @@ static void setup_descriptors(struct voicebus *vb)
INIT_LIST_HEAD(&buffers);
- for (i = 0; i < vb->min_tx_buffer_count; ++i) {
- vbb = kmem_cache_alloc(buffer_cache, GFP_KERNEL);
- if (unlikely(NULL == vbb))
- BUG_ON(1);
- else
- list_add_tail(&vbb->entry, &buffers);
+ if (test_bit(VOICEBUS_NORMAL_MODE, &vb->flags)) {
+ for (i = 0; i < vb->min_tx_buffer_count; ++i) {
+ vbb = kmem_cache_alloc(buffer_cache, GFP_KERNEL);
+ if (unlikely(NULL == vbb))
+ BUG_ON(1);
+ else
+ list_add_tail(&vbb->entry, &buffers);
+ }
+
+ tasklet_disable(&vb->tasklet);
+ handle_transmit(vb, &buffers);
+ tasklet_enable(&vb->tasklet);
+
+ spin_lock_irqsave(&vb->lock, flags);
+ list_for_each_entry(vbb, &buffers, entry)
+ voicebus_transmit(vb, vbb);
+ spin_unlock_irqrestore(&vb->lock, flags);
}
- tasklet_disable(&vb->tasklet);
- handle_transmit(vb, &buffers);
- tasklet_enable(&vb->tasklet);
-
- spin_lock_irqsave(&vb->lock, flags);
- list_for_each_entry(vbb, &buffers, entry)
- voicebus_transmit(vb, vbb);
- spin_unlock_irqrestore(&vb->lock, flags);
}
static void
@@ -767,14 +744,14 @@ show_buffer(struct voicebus *vb, struct vbb *vbb)
* voicebus_transmit - Queue a buffer on the hardware descriptor ring.
*
*/
-int voicebus_transmit(struct voicebus *vb, struct vbb *vbb)
+static int __voicebus_transmit(struct voicebus *vb, struct vbb *vbb)
{
struct voicebus_descriptor *d;
struct voicebus_descriptor_list *dl = &vb->txd;
d = vb_descriptor(dl, dl->tail);
- if (unlikely(d->buffer1 != vb->idle_vbb_dma_addr)) {
+ if (unlikely((d->buffer1 != vb->idle_vbb_dma_addr) && d->buffer1)) {
if (printk_ratelimit())
dev_warn(&vb->pdev->dev, "Dropping tx buffer buffer\n");
voicebus_free(vb, vbb);
@@ -792,6 +769,24 @@ int voicebus_transmit(struct voicebus *vb, struct vbb *vbb)
atomic_inc(&dl->count);
return 0;
}
+
+/*!
+ * \brief Instruct the hardware to check for a new tx descriptor.
+ */
+static inline void
+__vb_tx_demand_poll(struct voicebus *vb)
+{
+ u32 status = __vb_getctl(vb, 0x0028);
+ if ((status & 0x00700000) == 0x00600000)
+ __vb_setctl(vb, 0x0008, 0x00000000);
+}
+
+int voicebus_transmit(struct voicebus *vb, struct vbb *vbb)
+{
+ __voicebus_transmit(vb, vbb);
+ __vb_tx_demand_poll(vb);
+ return 0;
+}
EXPORT_SYMBOL(voicebus_transmit);
/*!
@@ -817,24 +812,29 @@ vb_get_completed_txb(struct voicebus *vb)
d = vb_descriptor(dl, head);
- if (OWNED(d) || (d->buffer1 == vb->idle_vbb_dma_addr))
+ if (OWNED(d) || !d->buffer1 || (d->buffer1 == vb->idle_vbb_dma_addr))
return NULL;
dma_unmap_single(&vb->pdev->dev, d->buffer1,
sizeof(vbb->data), DMA_TO_DEVICE);
vbb = dl->pending[head];
- dl->pending[head] = vb->idle_vbb;
+ if (test_bit(VOICEBUS_NORMAL_MODE, &vb->flags)) {
+ d->buffer1 = vb->idle_vbb_dma_addr;
+ dl->pending[head] = vb->idle_vbb;
+ SET_OWNED(d);
+ } else {
+ d->buffer1 = 0;
+ dl->pending[head] = NULL;
+ }
dl->head = (++head) & DRING_MASK;
- d->buffer1 = vb->idle_vbb_dma_addr;
- SET_OWNED(d);
atomic_dec(&dl->count);
vb_net_capture_vbb(vb, vbb, 1, d->des0, d->container);
return vbb;
}
static void *
-vb_get_completed_rxb(struct voicebus *vb)
+vb_get_completed_rxb(struct voicebus *vb, u32 *des0)
{
struct voicebus_descriptor *d;
struct voicebus_descriptor_list *dl = &vb->rxd;
@@ -855,6 +855,7 @@ vb_get_completed_rxb(struct voicebus *vb)
# ifdef VOICEBUS_NET_DEBUG
vb_net_capture_vbb(vb, vbb, 0, d->des0, d->container);
# endif
+ *des0 = le32_to_cpu(d->des0);
return vbb;
}
@@ -867,15 +868,8 @@ voicebus_free(struct voicebus *vb, struct vbb *vbb)
{
kmem_cache_free(buffer_cache, vbb);
}
+EXPORT_SYMBOL(voicebus_free);
-/*!
- * \brief Instruct the hardware to check for a new tx descriptor.
- */
-static inline void
-__vb_tx_demand_poll(struct voicebus *vb)
-{
- __vb_setctl(vb, 0x0008, 0x00000000);
-}
/*!
* \brief Command the hardware to check if it owns the next receive
@@ -884,13 +878,17 @@ __vb_tx_demand_poll(struct voicebus *vb)
static inline void
__vb_rx_demand_poll(struct voicebus *vb)
{
- __vb_setctl(vb, 0x0010, 0x00000000);
+ if (((__vb_getctl(vb, 0x0028) >> 17) & 0x7) == 0x4)
+ __vb_setctl(vb, 0x0010, 0x00000000);
}
static void
__vb_enable_interrupts(struct voicebus *vb)
{
- __vb_setctl(vb, IER_CSR7, DEFAULT_INTERRUPTS);
+ if (test_bit(VOICEBUS_NORMAL_MODE, &vb->flags))
+ __vb_setctl(vb, IER_CSR7, DEFAULT_NORMAL_INTERRUPTS);
+ else
+ __vb_setctl(vb, IER_CSR7, DEFAULT_NO_IDLE_INTERRUPTS);
}
static void
@@ -914,8 +912,8 @@ static void start_packet_processing(struct voicebus *vb)
u32 reg;
VBLOCK(vb);
- clear_bit(STOP, &vb->flags);
- clear_bit(STOPPED, &vb->flags);
+ clear_bit(VOICEBUS_STOP, &vb->flags);
+ clear_bit(VOICEBUS_STOPPED, &vb->flags);
#if defined(CONFIG_VOICEBUS_TIMER)
vb->timer.expires = jiffies + HZ/1000;
add_timer(&vb->timer);
@@ -1004,7 +1002,7 @@ voicebus_stop(struct voicebus *vb)
if (vb_is_stopped(vb))
return 0;
- set_bit(STOP, &vb->flags);
+ set_bit(VOICEBUS_STOP, &vb->flags);
vb_stop_txrx_processors(vb);
if (!vb_is_stopped(vb)) {
@@ -1024,7 +1022,7 @@ voicebus_stop(struct voicebus *vb)
}
}
- set_bit(STOPPED, &vb->flags);
+ set_bit(VOICEBUS_STOPPED, &vb->flags);
#if defined(CONFIG_VOICEBUS_TIMER)
del_timer_sync(&vb->timer);
@@ -1091,7 +1089,7 @@ vb_increase_latency(struct voicebus *vb, unsigned int increase,
if (0 == increase)
return;
- if (test_bit(LATENCY_LOCKED, &vb->flags))
+ if (test_bit(VOICEBUS_LATENCY_LOCKED, &vb->flags))
return;
if (unlikely(increase > VOICEBUS_MAXLATENCY_BUMP))
@@ -1160,6 +1158,7 @@ static void vb_deferred(struct voicebus *vb)
int behind = 0;
const int DEFAULT_COUNT = 5;
int count = DEFAULT_COUNT;
+ u32 des0 = 0;
/* First, temporarily store any non-idle buffers that the hardware has
* indicated it's finished transmitting. Non idle buffers are those
@@ -1252,7 +1251,7 @@ static void vb_deferred(struct voicebus *vb)
* hardware, resulting in a hard underrun condition. */
if (unlikely(softunderrun)) {
#if !defined(CONFIG_VOICEBUS_SYSFS)
- if (!test_bit(LATENCY_LOCKED, &vb->flags) &&
+ if (!test_bit(VOICEBUS_LATENCY_LOCKED, &vb->flags) &&
printk_ratelimit()) {
if (vb->max_latency != vb->min_tx_buffer_count) {
dev_info(&vb->pdev->dev, "Missed interrupt. "
@@ -1272,13 +1271,20 @@ static void vb_deferred(struct voicebus *vb)
/* If there may still be buffers in the descriptor rings, reschedule
* ourself to run again. We essentially yield here to allow any other
* cards a chance to run. */
- if (unlikely(!count && !test_bit(STOP, &vb->flags)))
+ if (unlikely(!count && !test_bit(VOICEBUS_STOP, &vb->flags)))
tasklet_hi_schedule(&vb->tasklet);
/* And finally, pass up any receive buffers. */
count = DEFAULT_COUNT;
- while (--count && (vbb = vb_get_completed_rxb(vb)))
- list_add_tail(&vbb->entry, &buffers);
+ while (--count && (vbb = vb_get_completed_rxb(vb, &des0))) {
+ if (((des0 >> 16) & 0x7fff) != VOICEBUS_SFRAME_SIZE) {
+ dev_dbg(&vb->pdev->dev,
+ "ERROR: Dropping packet of wrong size. (%d)\n",
+ (des0>>16)&0x7fff);
+ } else {
+ list_add_tail(&vbb->entry, &buffers);
+ }
+ }
handle_receive(vb, &buffers);
list_for_each_entry(vbb, &buffers, entry)
@@ -1311,7 +1317,8 @@ static void handle_hardunderrun(struct work_struct *work)
struct voicebus *vb = container_of(work, struct voicebus,
underrun_work);
#endif
- if (test_bit(STOP, &vb->flags) || test_bit(STOPPED, &vb->flags))
+ if (test_bit(VOICEBUS_STOP, &vb->flags) ||
+ test_bit(VOICEBUS_STOPPED, &vb->flags))
return;
if (printk_ratelimit()) {
@@ -1358,28 +1365,29 @@ vb_isr(int irq, void *dev_id)
if (unlikely((int_status &
(TX_UNAVAILABLE_INTERRUPT|RX_UNAVAILABLE_INTERRUPT)) &&
- !test_bit(STOP, &vb->flags))) {
+ !test_bit(VOICEBUS_STOP, &vb->flags))) {
schedule_work(&vb->underrun_work);
__vb_setctl(vb, SR_CSR5, int_status);
- } else if (likely(int_status & TX_COMPLETE_INTERRUPT)) {
+ } else if (likely(int_status &
+ (TX_COMPLETE_INTERRUPT|RX_COMPLETE_INTERRUPT))) {
/* ******************************************************** */
/* NORMAL INTERRUPT CASE */
/* ******************************************************** */
tasklet_hi_schedule(&vb->tasklet);
- __vb_setctl(vb, SR_CSR5, TX_COMPLETE_INTERRUPT);
+ __vb_setctl(vb, SR_CSR5, TX_COMPLETE_INTERRUPT|RX_COMPLETE_INTERRUPT);
} else {
if (int_status & FATAL_BUS_ERROR_INTERRUPT)
dev_err(&vb->pdev->dev, "Fatal Bus Error detected!\n");
if (int_status & TX_STOPPED_INTERRUPT) {
- BUG_ON(!test_bit(STOP, &vb->flags));
+ BUG_ON(!test_bit(VOICEBUS_STOP, &vb->flags));
if (__vb_is_stopped(vb)) {
__vb_disable_interrupts(vb);
complete(&vb->stopped_completion);
}
}
if (int_status & RX_STOPPED_INTERRUPT) {
- BUG_ON(!test_bit(STOP, &vb->flags));
+ BUG_ON(!test_bit(VOICEBUS_STOP, &vb->flags));
if (__vb_is_stopped(vb)) {
__vb_disable_interrupts(vb);
complete(&vb->stopped_completion);
@@ -1407,7 +1415,7 @@ vb_timer(unsigned long data)
#else
vb_isr(0, vb);
#endif
- if (!test_bit(STOPPED, &vb->flags)) {
+ if (!test_bit(VOICEBUS_STOPPED, &vb->flags)) {
vb->timer.expires = start + HZ/1000;
add_timer(&vb->timer);
}
@@ -1427,7 +1435,7 @@ static void vb_tasklet(unsigned long data)
* \todo Complete this description.
*/
int
-voicebus_init(struct voicebus *vb, const char *board_name)
+__voicebus_init(struct voicebus *vb, const char *board_name, int normal_mode)
{
int retval = 0;
@@ -1444,8 +1452,13 @@ voicebus_init(struct voicebus *vb, const char *board_name)
spin_lock_init(&vb->lock);
init_completion(&vb->stopped_completion);
- set_bit(STOP, &vb->flags);
- clear_bit(IN_DEFERRED_PROCESSING, &vb->flags);
+ set_bit(VOICEBUS_STOP, &vb->flags);
+
+ if (normal_mode)
+ set_bit(VOICEBUS_NORMAL_MODE, &vb->flags);
+ else
+ clear_bit(VOICEBUS_NORMAL_MODE, &vb->flags);
+
vb->min_tx_buffer_count = VOICEBUS_DEFAULT_LATENCY;
INIT_LIST_HEAD(&vb->tx_complete);
@@ -1558,7 +1571,7 @@ cleanup:
retval = -EIO;
return retval;
}
-EXPORT_SYMBOL(voicebus_init);
+EXPORT_SYMBOL(__voicebus_init);
static spinlock_t loader_list_lock;
static LIST_HEAD(binary_loader_list);
@@ -1670,7 +1683,7 @@ static int __init voicebus_module_init(void)
NULL);
#endif
#else
-#ifdef DEBUG
+#if (defined(DEBUG) && defined(CONFIG_SLAB_DEBUG))
buffer_cache = kmem_cache_create(THIS_MODULE->name,
sizeof(struct vbb), 0,
SLAB_HWCACHE_ALIGN | SLAB_STORE_USER |
diff --git a/drivers/dahdi/voicebus/voicebus.h b/drivers/dahdi/voicebus/voicebus.h
index a58e4ca..149b4d0 100644
--- a/drivers/dahdi/voicebus/voicebus.h
+++ b/drivers/dahdi/voicebus/voicebus.h
@@ -84,6 +84,13 @@ struct voicebus_descriptor_list {
unsigned int padding;
};
+/* Bit definitions for struct voicebus.flags */
+#define VOICEBUS_STOP 1
+#define VOICEBUS_STOPPED 2
+#define VOICEBUS_LATENCY_LOCKED 3
+#define VOICEBUS_NORMAL_MODE 4
+#define VOICEBUS_USERMODE 5
+
/**
* struct voicebus - Represents physical interface to voicebus card.
*
@@ -125,7 +132,8 @@ struct voicebus {
#endif
};
-int voicebus_init(struct voicebus *vb, const char *board_name);
+int __voicebus_init(struct voicebus *vb, const char *board_name,
+ int normal_mode);
void voicebus_release(struct voicebus *vb);
int voicebus_start(struct voicebus *vb);
int voicebus_stop(struct voicebus *vb);
@@ -133,8 +141,47 @@ void voicebus_free(struct voicebus *vb, struct vbb *vbb);
int voicebus_transmit(struct voicebus *vb, struct vbb *vbb);
int voicebus_set_minlatency(struct voicebus *vb, unsigned int milliseconds);
int voicebus_current_latency(struct voicebus *vb);
-void voicebus_lock_latency(struct voicebus *vb);
-void voicebus_unlock_latency(struct voicebus *vb);
-int voicebus_is_latency_locked(const struct voicebus *vb);
+static inline int voicebus_init(struct voicebus *vb, const char *board_name)
+{
+ return __voicebus_init(vb, board_name, 1);
+}
+
+static inline int
+voicebus_no_idle_init(struct voicebus *vb, const char *board_name)
+{
+ return __voicebus_init(vb, board_name, 0);
+}
+
+/**
+ * voicebus_lock_latency() - Do not increase the latency during underruns.
+ *
+ */
+static inline void voicebus_lock_latency(struct voicebus *vb)
+{
+ set_bit(VOICEBUS_LATENCY_LOCKED, &vb->flags);
+}
+
+/**
+ * voicebus_unlock_latency() - Bump up the latency during underruns.
+ *
+ */
+static inline void voicebus_unlock_latency(struct voicebus *vb)
+{
+ clear_bit(VOICEBUS_LATENCY_LOCKED, &vb->flags);
+}
+
+/**
+ * voicebus_is_latency_locked() - Return 1 if latency is currently locked.
+ *
+ */
+static inline int voicebus_is_latency_locked(const struct voicebus *vb)
+{
+ return test_bit(VOICEBUS_LATENCY_LOCKED, &vb->flags);
+}
+
+static inline void voicebus_set_normal_mode(struct voicebus *vb)
+{
+ set_bit(VOICEBUS_NORMAL_MODE, &vb->flags);
+}
#endif /* __VOICEBUS_H__ */