summaryrefslogtreecommitdiff
path: root/drivers/dahdi/wctdm24xxp
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2011-08-18 19:21:44 +0000
committerShaun Ruffell <sruffell@digium.com>2011-08-18 19:21:44 +0000
commit031ad0b6e263aa45736a2d3ec5b740b02759638a (patch)
treee5f51bf5d033857873533a946f98be817d8c22ef /drivers/dahdi/wctdm24xxp
parent8179fc1e2eb2ad55453d420f9247384c91b07c2c (diff)
wctdm24xxp: Use our own free list for IRQ commands.
Really only *necessary* when SLAB debugging is enabled, but in that case, can reduce the chance of latency bumps when first loading the driver. Otherwise the constant slab poisoning / checking in interrupt context from the kmalloc / kfrees is too much. 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@10144 a0bf4364-ded3-4de4-8d8a-66a801d63aff
Diffstat (limited to 'drivers/dahdi/wctdm24xxp')
-rw-r--r--drivers/dahdi/wctdm24xxp/base.c52
-rw-r--r--drivers/dahdi/wctdm24xxp/wctdm24xxp.h1
2 files changed, 48 insertions, 5 deletions
diff --git a/drivers/dahdi/wctdm24xxp/base.c b/drivers/dahdi/wctdm24xxp/base.c
index fc95815..facbd1b 100644
--- a/drivers/dahdi/wctdm24xxp/base.c
+++ b/drivers/dahdi/wctdm24xxp/base.c
@@ -867,6 +867,8 @@ static void _cmd_decipher(struct wctdm *wc, const u8 *eframe, int card)
return;
}
+ list_add(&cmd->node, &wc->free_isr_commands);
+
switch (mod->type) {
case FXS:
mod->isrshadow[(68 == address) ? 0 : 1] = value;
@@ -884,8 +886,6 @@ static void _cmd_decipher(struct wctdm *wc, const u8 *eframe, int card)
default:
break;
}
-
- kfree(cmd);
}
/* Call with wc.reglock held and local interrupts disabled. */
@@ -894,9 +894,15 @@ wctdm_isr_getreg(struct wctdm *wc, struct wctdm_module *const mod, u8 address)
{
struct wctdm_cmd *cmd;
- cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC);
- if (unlikely(!cmd))
- return;
+ if (!list_empty(&wc->free_isr_commands)) {
+ cmd = list_entry(wc->free_isr_commands.next,
+ struct wctdm_cmd, node);
+ list_del(&cmd->node);
+ } else {
+ cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC);
+ if (unlikely(!cmd))
+ return;
+ }
cmd->cmd = CMD_RD(address);
cmd->complete = NULL;
@@ -4633,6 +4639,7 @@ static void wctdm_back_out_gracefully(struct wctdm *wc)
list_splice_init(&mod->pending_cmds, &local_list);
list_splice_init(&mod->active_cmds, &local_list);
}
+ list_splice_init(&wc->free_isr_commands, &local_list);
spin_unlock_irqrestore(&wc->reglock, flags);
while (!list_empty(&local_list)) {
@@ -5221,6 +5228,39 @@ static void wctdm_set_tdm410_leds(struct wctdm *wc)
}
}
+/**
+ * wctdm_allocate_irq_commands - Preallocate some commands for use in interrupt context.
+ * @wc: The board which we're allocating for.
+ * @count: The number of IRQ commands to allocate.
+ *
+ * We need a minimum of 4 * the current latency worth of commands for each
+ * analog module. When the latency grows, new commands will be allocated, but
+ * this just represents are best guess as to the number of commands we'll need
+ * after probing for modules, and reduces the chance that we'll allocate
+ * memory in interrupt context when the driver first loads.
+ *
+ */
+static void wctdm_allocate_irq_commands(struct wctdm *wc, unsigned int count)
+{
+ unsigned long flags;
+ LIST_HEAD(local_list);
+
+ if (!count)
+ return;
+
+ while (count--) {
+ struct wctdm_cmd *cmd;
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd)
+ break;
+ list_add(&cmd->node, &local_list);
+ }
+
+ spin_lock_irqsave(&wc->reglock, flags);
+ list_splice(&local_list, &wc->free_isr_commands);
+ spin_unlock_irqrestore(&wc->reglock, flags);
+}
+
#ifdef USE_ASYNC_INIT
struct async_data {
struct pci_dev *pdev;
@@ -5266,6 +5306,7 @@ __wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
spin_lock_init(&wc->frame_list_lock);
init_waitqueue_head(&wc->regq);
spin_lock_init(&wc->reglock);
+ INIT_LIST_HEAD(&wc->free_isr_commands);
wc->oldsync = -1;
wc->board_name = kasprintf(GFP_KERNEL, "%s%d", wctdm_driver.name, pos);
@@ -5492,6 +5533,7 @@ __wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
}
+ wctdm_allocate_irq_commands(wc, anamods * latency * 4);
wc->not_ready--;
dev_info(&wc->vb.pdev->dev,
diff --git a/drivers/dahdi/wctdm24xxp/wctdm24xxp.h b/drivers/dahdi/wctdm24xxp/wctdm24xxp.h
index 4ab313d..b71a8aa 100644
--- a/drivers/dahdi/wctdm24xxp/wctdm24xxp.h
+++ b/drivers/dahdi/wctdm24xxp/wctdm24xxp.h
@@ -255,6 +255,7 @@ struct wctdm {
spinlock_t reglock; /* held when accessing anything affecting the module array */
wait_queue_head_t regq;
+ struct list_head free_isr_commands;
struct wctdm_module mods[NUM_MODULES];