wcte12xp, wctdm24xxp: Convert vbb cache from kmem_cache to dma_pool.
The voicebus interface constantly uses the same buffers for moving data to/from the card. A fixed pool has less overhead in this case than constantly mapping/unmapping the kmem_cache_alloced buffers. Saves about ~2.608 us for each run of vb_isr on a 2.40 GHz Xeon test machine. Signed-off-by: Shaun Ruffell <sruffell@digium.com> Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9402 a0bf4364-ded3-4de4-8d8a-66a801d63aff
This commit is contained in:
parent
9038e0a2cd
commit
5618e9e812
@ -199,13 +199,6 @@ EXPORT_SYMBOL(dahdi_fifo_alloc);
|
|||||||
#endif /* CONFIG_VOICEBUS_ECREFERENCE */
|
#endif /* CONFIG_VOICEBUS_ECREFERENCE */
|
||||||
|
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
|
||||||
kmem_cache_t *voicebus_vbb_cache;
|
|
||||||
#else
|
|
||||||
struct kmem_cache *voicebus_vbb_cache;
|
|
||||||
#endif
|
|
||||||
EXPORT_SYMBOL(voicebus_vbb_cache);
|
|
||||||
|
|
||||||
/* In memory structure shared by the host and the adapter. */
|
/* In memory structure shared by the host and the adapter. */
|
||||||
struct voicebus_descriptor {
|
struct voicebus_descriptor {
|
||||||
volatile __le32 des0;
|
volatile __le32 des0;
|
||||||
@ -480,16 +473,15 @@ vb_cleanup_tx_descriptors(struct voicebus *vb)
|
|||||||
while (!list_empty(&vb->tx_complete)) {
|
while (!list_empty(&vb->tx_complete)) {
|
||||||
vbb = list_entry(vb->tx_complete.next, struct vbb, entry);
|
vbb = list_entry(vb->tx_complete.next, struct vbb, entry);
|
||||||
list_del(&vbb->entry);
|
list_del(&vbb->entry);
|
||||||
kmem_cache_free(voicebus_vbb_cache, vbb);
|
dma_pool_free(vb->pool, vbb, vbb->dma_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < DRING_SIZE; ++i) {
|
for (i = 0; i < DRING_SIZE; ++i) {
|
||||||
d = vb_descriptor(dl, i);
|
d = vb_descriptor(dl, i);
|
||||||
if (d->buffer1 && (d->buffer1 != vb->idle_vbb_dma_addr)) {
|
if (d->buffer1 && (d->buffer1 != vb->idle_vbb_dma_addr)) {
|
||||||
WARN_ON(!dl->pending[i]);
|
WARN_ON(!dl->pending[i]);
|
||||||
dma_unmap_single(&vb->pdev->dev, d->buffer1,
|
vbb = dl->pending[i];
|
||||||
VOICEBUS_SFRAME_SIZE, DMA_TO_DEVICE);
|
dma_pool_free(vb->pool, vbb, vbb->dma_addr);
|
||||||
kmem_cache_free(voicebus_vbb_cache, dl->pending[i]);
|
|
||||||
}
|
}
|
||||||
if (NORMAL == vb->mode) {
|
if (NORMAL == vb->mode) {
|
||||||
d->des1 |= 0x80000000;
|
d->des1 |= 0x80000000;
|
||||||
@ -519,8 +511,6 @@ static void vb_cleanup_rx_descriptors(struct voicebus *vb)
|
|||||||
for (i = 0; i < DRING_SIZE; ++i) {
|
for (i = 0; i < DRING_SIZE; ++i) {
|
||||||
d = vb_descriptor(dl, i);
|
d = vb_descriptor(dl, i);
|
||||||
if (d->buffer1) {
|
if (d->buffer1) {
|
||||||
dma_unmap_single(&vb->pdev->dev, d->buffer1,
|
|
||||||
VOICEBUS_SFRAME_SIZE, DMA_FROM_DEVICE);
|
|
||||||
d->buffer1 = 0;
|
d->buffer1 = 0;
|
||||||
BUG_ON(!dl->pending[i]);
|
BUG_ON(!dl->pending[i]);
|
||||||
vbb = dl->pending[i];
|
vbb = dl->pending[i];
|
||||||
@ -560,7 +550,7 @@ vb_free_descriptors(struct voicebus *vb, struct voicebus_descriptor_list *dl)
|
|||||||
while (!list_empty(&vb->free_rx)) {
|
while (!list_empty(&vb->free_rx)) {
|
||||||
vbb = list_entry(vb->free_rx.next, struct vbb, entry);
|
vbb = list_entry(vb->free_rx.next, struct vbb, entry);
|
||||||
list_del(&vbb->entry);
|
list_del(&vbb->entry);
|
||||||
kmem_cache_free(voicebus_vbb_cache, vbb);
|
dma_pool_free(vb->pool, vbb, vbb->dma_addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -713,8 +703,7 @@ vb_submit_rxb(struct voicebus *vb, struct vbb *vbb)
|
|||||||
|
|
||||||
dl->pending[tail] = vbb;
|
dl->pending[tail] = vbb;
|
||||||
dl->tail = (++tail) & DRING_MASK;
|
dl->tail = (++tail) & DRING_MASK;
|
||||||
d->buffer1 = dma_map_single(&vb->pdev->dev, vbb->data,
|
d->buffer1 = vbb->dma_addr;
|
||||||
sizeof(vbb->data), DMA_FROM_DEVICE);
|
|
||||||
SET_OWNED(d); /* That's it until the hardware is done with it. */
|
SET_OWNED(d); /* That's it until the hardware is done with it. */
|
||||||
atomic_inc(&dl->count);
|
atomic_inc(&dl->count);
|
||||||
return 0;
|
return 0;
|
||||||
@ -730,7 +719,7 @@ static int __voicebus_transmit(struct voicebus *vb, struct vbb *vbb)
|
|||||||
if (unlikely((d->buffer1 != vb->idle_vbb_dma_addr) && d->buffer1)) {
|
if (unlikely((d->buffer1 != vb->idle_vbb_dma_addr) && d->buffer1)) {
|
||||||
if (printk_ratelimit())
|
if (printk_ratelimit())
|
||||||
dev_warn(&vb->pdev->dev, "Dropping tx buffer buffer\n");
|
dev_warn(&vb->pdev->dev, "Dropping tx buffer buffer\n");
|
||||||
kmem_cache_free(voicebus_vbb_cache, vbb);
|
dma_pool_free(vb->pool, vbb, vbb->dma_addr);
|
||||||
/* Schedule the underrun handler to run here, since we'll need
|
/* Schedule the underrun handler to run here, since we'll need
|
||||||
* to cleanup as best we can. */
|
* to cleanup as best we can. */
|
||||||
schedule_work(&vb->underrun_work);
|
schedule_work(&vb->underrun_work);
|
||||||
@ -738,8 +727,7 @@ static int __voicebus_transmit(struct voicebus *vb, struct vbb *vbb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dl->pending[dl->tail] = vbb;
|
dl->pending[dl->tail] = vbb;
|
||||||
d->buffer1 = dma_map_single(&vb->pdev->dev, vbb->data,
|
d->buffer1 = vbb->dma_addr;
|
||||||
sizeof(vbb->data), DMA_TO_DEVICE);
|
|
||||||
dl->tail = (dl->tail + 1) & DRING_MASK;
|
dl->tail = (dl->tail + 1) & DRING_MASK;
|
||||||
SET_OWNED(d); /* That's it until the hardware is done with it. */
|
SET_OWNED(d); /* That's it until the hardware is done with it. */
|
||||||
atomic_inc(&dl->count);
|
atomic_inc(&dl->count);
|
||||||
@ -774,6 +762,7 @@ static void setup_descriptors(struct voicebus *vb)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct vbb *vbb;
|
struct vbb *vbb;
|
||||||
|
dma_addr_t dma_addr;
|
||||||
LIST_HEAD(buffers);
|
LIST_HEAD(buffers);
|
||||||
|
|
||||||
might_sleep();
|
might_sleep();
|
||||||
@ -787,7 +776,10 @@ static void setup_descriptors(struct voicebus *vb)
|
|||||||
|
|
||||||
for (i = 0; i < DRING_SIZE; ++i) {
|
for (i = 0; i < DRING_SIZE; ++i) {
|
||||||
if (list_empty(&vb->free_rx)) {
|
if (list_empty(&vb->free_rx)) {
|
||||||
vbb = kmem_cache_alloc(voicebus_vbb_cache, GFP_KERNEL);
|
vbb = dma_pool_alloc(vb->pool, GFP_KERNEL,
|
||||||
|
&dma_addr);
|
||||||
|
if (vbb)
|
||||||
|
vbb->dma_addr = dma_addr;
|
||||||
} else {
|
} else {
|
||||||
vbb = list_entry(vb->free_rx.next, struct vbb, entry);
|
vbb = list_entry(vb->free_rx.next, struct vbb, entry);
|
||||||
list_del(&vbb->entry);
|
list_del(&vbb->entry);
|
||||||
@ -807,11 +799,13 @@ static void setup_descriptors(struct voicebus *vb)
|
|||||||
|
|
||||||
if (BOOT != vb->mode) {
|
if (BOOT != vb->mode) {
|
||||||
for (i = 0; i < vb->min_tx_buffer_count; ++i) {
|
for (i = 0; i < vb->min_tx_buffer_count; ++i) {
|
||||||
vbb = kmem_cache_alloc(voicebus_vbb_cache, GFP_KERNEL);
|
vbb = dma_pool_alloc(vb->pool, GFP_KERNEL,
|
||||||
|
&dma_addr);
|
||||||
if (unlikely(NULL == vbb))
|
if (unlikely(NULL == vbb))
|
||||||
BUG_ON(1);
|
BUG_ON(1);
|
||||||
else
|
|
||||||
list_add_tail(&vbb->entry, &buffers);
|
vbb->dma_addr = dma_addr;
|
||||||
|
list_add_tail(&vbb->entry, &buffers);
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_transmit(vb, &buffers);
|
handle_transmit(vb, &buffers);
|
||||||
@ -929,9 +923,6 @@ vb_get_completed_txb(struct voicebus *vb)
|
|||||||
if (OWNED(d) || !d->buffer1 || (d->buffer1 == vb->idle_vbb_dma_addr))
|
if (OWNED(d) || !d->buffer1 || (d->buffer1 == vb->idle_vbb_dma_addr))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
dma_unmap_single(&vb->pdev->dev, d->buffer1,
|
|
||||||
sizeof(vbb->data), DMA_TO_DEVICE);
|
|
||||||
|
|
||||||
vbb = dl->pending[head];
|
vbb = dl->pending[head];
|
||||||
if (NORMAL == vb->mode) {
|
if (NORMAL == vb->mode) {
|
||||||
d->buffer1 = vb->idle_vbb_dma_addr;
|
d->buffer1 = vb->idle_vbb_dma_addr;
|
||||||
@ -960,8 +951,6 @@ vb_get_completed_rxb(struct voicebus *vb, u32 *des0)
|
|||||||
if ((0 == d->buffer1) || OWNED(d))
|
if ((0 == d->buffer1) || OWNED(d))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
dma_unmap_single(&vb->pdev->dev, d->buffer1,
|
|
||||||
sizeof(vbb->data), DMA_FROM_DEVICE);
|
|
||||||
vbb = dl->pending[head];
|
vbb = dl->pending[head];
|
||||||
dl->head = (++head) & DRING_MASK;
|
dl->head = (++head) & DRING_MASK;
|
||||||
d->buffer1 = 0;
|
d->buffer1 = 0;
|
||||||
@ -1190,6 +1179,7 @@ voicebus_release(struct voicebus *vb)
|
|||||||
pci_iounmap(vb->pdev, vb->iobase);
|
pci_iounmap(vb->pdev, vb->iobase);
|
||||||
pci_clear_mwi(vb->pdev);
|
pci_clear_mwi(vb->pdev);
|
||||||
pci_disable_device(vb->pdev);
|
pci_disable_device(vb->pdev);
|
||||||
|
dma_pool_destroy(vb->pool);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(voicebus_release);
|
EXPORT_SYMBOL(voicebus_release);
|
||||||
|
|
||||||
@ -1226,10 +1216,13 @@ vb_increase_latency(struct voicebus *vb, unsigned int increase,
|
|||||||
/* Set the minimum latency in case we're restarted...we don't want to
|
/* Set the minimum latency in case we're restarted...we don't want to
|
||||||
* wait for the buffer to grow to this depth again in that case. */
|
* wait for the buffer to grow to this depth again in that case. */
|
||||||
for (i = 0; i < increase; ++i) {
|
for (i = 0; i < increase; ++i) {
|
||||||
vbb = kmem_cache_alloc(voicebus_vbb_cache, GFP_ATOMIC);
|
dma_addr_t dma_addr;
|
||||||
|
vbb = dma_pool_alloc(vb->pool, GFP_ATOMIC, &dma_addr);
|
||||||
WARN_ON(NULL == vbb);
|
WARN_ON(NULL == vbb);
|
||||||
if (likely(NULL != vbb))
|
if (likely(NULL != vbb)) {
|
||||||
|
vbb->dma_addr = dma_addr;
|
||||||
list_add_tail(&vbb->entry, &local);
|
list_add_tail(&vbb->entry, &local);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_transmit(vb, &local);
|
handle_transmit(vb, &local);
|
||||||
@ -1573,7 +1566,7 @@ tx_error_exit:
|
|||||||
while (!list_empty(&buffers)) {
|
while (!list_empty(&buffers)) {
|
||||||
vbb = list_entry(buffers.next, struct vbb, entry);
|
vbb = list_entry(buffers.next, struct vbb, entry);
|
||||||
list_del(&vbb->entry);
|
list_del(&vbb->entry);
|
||||||
kmem_cache_free(voicebus_vbb_cache, vbb);
|
dma_pool_free(vb->pool, vbb, vbb->dma_addr);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1785,6 +1778,13 @@ __voicebus_init(struct voicebus *vb, const char *board_name,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vb->pool = dma_pool_create(board_name, &vb->pdev->dev,
|
||||||
|
sizeof(struct vbb), 64, 0);
|
||||||
|
if (!vb->pool) {
|
||||||
|
retval = -ENOMEM;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
vb->idle_vbb = dma_alloc_coherent(&vb->pdev->dev, VOICEBUS_SFRAME_SIZE,
|
vb->idle_vbb = dma_alloc_coherent(&vb->pdev->dev, VOICEBUS_SFRAME_SIZE,
|
||||||
&vb->idle_vbb_dma_addr, GFP_KERNEL);
|
&vb->idle_vbb_dma_addr, GFP_KERNEL);
|
||||||
|
|
||||||
@ -1837,6 +1837,8 @@ cleanup:
|
|||||||
|
|
||||||
tasklet_kill(&vb->tasklet);
|
tasklet_kill(&vb->tasklet);
|
||||||
|
|
||||||
|
if (vb->pool)
|
||||||
|
dma_pool_destroy(vb->pool);
|
||||||
/* Cleanup memory and software resources. */
|
/* Cleanup memory and software resources. */
|
||||||
if (vb->txd.desc)
|
if (vb->txd.desc)
|
||||||
vb_free_descriptors(vb, &vb->txd);
|
vb_free_descriptors(vb, &vb->txd);
|
||||||
@ -1957,37 +1959,6 @@ static int __init voicebus_module_init(void)
|
|||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
|
|
||||||
voicebus_vbb_cache = kmem_cache_create(THIS_MODULE->name,
|
|
||||||
sizeof(struct vbb), 0,
|
|
||||||
#if defined(CONFIG_SLUB) && (LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 22))
|
|
||||||
SLAB_HWCACHE_ALIGN |
|
|
||||||
SLAB_STORE_USER, NULL,
|
|
||||||
NULL);
|
|
||||||
#else
|
|
||||||
SLAB_HWCACHE_ALIGN, NULL,
|
|
||||||
NULL);
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#if (defined(CONFIG_SLAB) && defined(CONFIG_SLAB_DEBUG)) || \
|
|
||||||
(defined(CONFIG_SLUB) && defined(CONFIG_SLUB_DEBUG))
|
|
||||||
voicebus_vbb_cache = kmem_cache_create(THIS_MODULE->name,
|
|
||||||
sizeof(struct vbb), 0,
|
|
||||||
SLAB_HWCACHE_ALIGN | SLAB_STORE_USER |
|
|
||||||
SLAB_POISON | SLAB_DEBUG_FREE, NULL);
|
|
||||||
#else
|
|
||||||
voicebus_vbb_cache = kmem_cache_create(THIS_MODULE->name,
|
|
||||||
sizeof(struct vbb), 0,
|
|
||||||
SLAB_HWCACHE_ALIGN, NULL);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (NULL == voicebus_vbb_cache) {
|
|
||||||
printk(KERN_ERR "%s: Failed to allocate buffer cache.\n",
|
|
||||||
THIS_MODULE->name);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This registration with dahdi.ko will fail since the span is not
|
/* This registration with dahdi.ko will fail since the span is not
|
||||||
* defined, but it will make sure that this module is a dependency of
|
* defined, but it will make sure that this module is a dependency of
|
||||||
* dahdi.ko, so that when it is being unloded, this module will be
|
* dahdi.ko, so that when it is being unloded, this module will be
|
||||||
@ -2002,7 +1973,6 @@ static int __init voicebus_module_init(void)
|
|||||||
|
|
||||||
static void __exit voicebus_module_cleanup(void)
|
static void __exit voicebus_module_cleanup(void)
|
||||||
{
|
{
|
||||||
kmem_cache_destroy(voicebus_vbb_cache);
|
|
||||||
WARN_ON(!list_empty(&binary_loader_list));
|
WARN_ON(!list_empty(&binary_loader_list));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +82,7 @@ struct voicebus;
|
|||||||
struct vbb {
|
struct vbb {
|
||||||
u8 data[VOICEBUS_SFRAME_SIZE];
|
u8 data[VOICEBUS_SFRAME_SIZE];
|
||||||
struct list_head entry;
|
struct list_head entry;
|
||||||
|
dma_addr_t dma_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct voicebus_operations {
|
struct voicebus_operations {
|
||||||
@ -157,6 +158,7 @@ struct voicebus {
|
|||||||
unsigned int max_latency;
|
unsigned int max_latency;
|
||||||
struct list_head tx_complete;
|
struct list_head tx_complete;
|
||||||
struct list_head free_rx;
|
struct list_head free_rx;
|
||||||
|
struct dma_pool *pool;
|
||||||
|
|
||||||
#ifdef VOICEBUS_NET_DEBUG
|
#ifdef VOICEBUS_NET_DEBUG
|
||||||
struct sk_buff_head captured_packets;
|
struct sk_buff_head captured_packets;
|
||||||
@ -170,12 +172,6 @@ struct voicebus {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
|
||||||
extern kmem_cache_t *voicebus_vbb_cache;
|
|
||||||
#else
|
|
||||||
extern struct kmem_cache *voicebus_vbb_cache;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int __voicebus_init(struct voicebus *vb, const char *board_name,
|
int __voicebus_init(struct voicebus *vb, const char *board_name,
|
||||||
enum voicebus_mode mode);
|
enum voicebus_mode mode);
|
||||||
void voicebus_release(struct voicebus *vb);
|
void voicebus_release(struct voicebus *vb);
|
||||||
|
@ -2223,7 +2223,7 @@ static void handle_hx8_transmit(struct voicebus *vb, struct list_head *buffers)
|
|||||||
|
|
||||||
list_for_each_entry_safe(vbb, n, buffers, entry) {
|
list_for_each_entry_safe(vbb, n, buffers, entry) {
|
||||||
list_del(&vbb->entry);
|
list_del(&vbb->entry);
|
||||||
kmem_cache_free(voicebus_vbb_cache, vbb);
|
dma_pool_free(vb->pool, vbb, vbb->dma_addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4408,6 +4408,7 @@ static int hx8_send_command(struct wctdm *wc, const u8 *command,
|
|||||||
struct sframe_packet *frame;
|
struct sframe_packet *frame;
|
||||||
const int MAX_COMMAND_LENGTH = 264 + 4;
|
const int MAX_COMMAND_LENGTH = 264 + 4;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
dma_addr_t dma_addr;
|
||||||
|
|
||||||
might_sleep();
|
might_sleep();
|
||||||
|
|
||||||
@ -4420,11 +4421,12 @@ static int hx8_send_command(struct wctdm *wc, const u8 *command,
|
|||||||
if (count > MAX_COMMAND_LENGTH)
|
if (count > MAX_COMMAND_LENGTH)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
vbb = kmem_cache_alloc(voicebus_vbb_cache, GFP_KERNEL);
|
vbb = dma_pool_alloc(wc->vb.pool, GFP_KERNEL, &dma_addr);
|
||||||
WARN_ON(!vbb);
|
WARN_ON(!vbb);
|
||||||
if (!vbb)
|
if (!vbb)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
vbb->dma_addr = dma_addr;
|
||||||
memset(vbb->data, 0, SFRAME_SIZE);
|
memset(vbb->data, 0, SFRAME_SIZE);
|
||||||
memcpy(&vbb->data[EFRAME_SIZE + EFRAME_GAP], command, count);
|
memcpy(&vbb->data[EFRAME_SIZE + EFRAME_GAP], command, count);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user