summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2011-03-11 15:15:40 -0600
committerShaun Ruffell <sruffell@digium.com>2011-04-15 14:19:00 -0500
commit5c29fda4c36404268b665d1248f3d8006ca6994c (patch)
tree80d1994cdccca252cabae27d1cde2d13bf70aff6
parent04701db43edce96ad9f9d35ee63e36f415e62b55 (diff)
wctdm24xxp: Allow more than one outstanding read at a time.
Since every read needs to go through the complete voicebus pipeline, if we know we're going to read multiple bytes we can queue them all up. Signed-off-by: Shaun Ruffell <sruffell@digium.com>
-rw-r--r--drivers/dahdi/wctdm24xxp/base.c75
1 files changed, 64 insertions, 11 deletions
diff --git a/drivers/dahdi/wctdm24xxp/base.c b/drivers/dahdi/wctdm24xxp/base.c
index d13ec1b..2397c91 100644
--- a/drivers/dahdi/wctdm24xxp/base.c
+++ b/drivers/dahdi/wctdm24xxp/base.c
@@ -1054,6 +1054,54 @@ int wctdm_getreg(struct wctdm *wc, struct wctdm_module *const mod, int addr)
return val;
}
+static int wctdm_getregs(struct wctdm *wc, struct wctdm_module *const mod,
+ int *const addresses, const size_t count)
+{
+ int x;
+ unsigned long flags;
+ struct wctdm_cmd *cmd;
+ struct wctdm_cmd **cmds = kmalloc(sizeof(cmd) * count, GFP_KERNEL);
+
+ if (!cmds)
+ return -ENOMEM;
+
+ for (x = 0; x < count; ++x) {
+ cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ kfree(cmds);
+ return -ENOMEM;
+ }
+
+ cmd->complete = kmalloc(sizeof(*cmd->complete), GFP_KERNEL);
+ if (!cmd->complete) {
+ kfree(cmd);
+ kfree(cmds);
+ return -ENOMEM;
+ }
+
+ init_completion(cmd->complete);
+
+ cmd->cmd = CMD_RD(addresses[x]);
+
+ spin_lock_irqsave(&wc->reglock, flags);
+ list_add_tail(&cmd->node, &mod->pending_cmds);
+ spin_unlock_irqrestore(&wc->reglock, flags);
+
+ cmds[x] = cmd;
+ }
+
+ for (x = count - 1; x >= 0; --x) {
+ cmd = cmds[x];
+ wait_for_completion(cmd->complete);
+ addresses[x] = cmd->cmd & 0xff;
+ kfree(cmd->complete);
+ kfree(cmd);
+ }
+
+ kfree(cmds);
+ return 0;
+}
+
/**
* call with wc->reglock held and interrupts disabled.
*/
@@ -1261,10 +1309,10 @@ wctdm_proslic_getreg_indirect(struct wctdm *wc, struct wctdm_module *const mod,
if (!wait_access(wc, mod)) {
wctdm_setreg(wc, mod, IAA, address);
if (!wait_access(wc, mod)) {
- unsigned char data1, data2;
- data1 = wctdm_getreg(wc, mod, IDA_LO);
- data2 = wctdm_getreg(wc, mod, IDA_HI);
- res = data1 | (data2 << 8);
+ int addresses[2] = {IDA_LO, IDA_HI};
+ wctdm_getregs(wc, mod, addresses,
+ ARRAY_SIZE(addresses));
+ res = addresses[0] | (addresses[1] << 8);
} else
p = "Failed to wait inside\n";
} else
@@ -2180,13 +2228,14 @@ static void handle_hx8_transmit(struct voicebus *vb, struct list_head *buffers)
static int wctdm_voicedaa_insane(struct wctdm *wc, struct wctdm_module *mod)
{
- int blah;
- blah = wctdm_getreg(wc, mod, 2);
- if (blah != 0x3)
+ int blah[] = {2, 11};
+ wctdm_getregs(wc, mod, blah, ARRAY_SIZE(blah));
+ if (blah[0] != 0x3)
return -2;
- blah = wctdm_getreg(wc, mod, 11);
- if (debug & DEBUG_CARD)
- dev_info(&wc->vb.pdev->dev, "VoiceDAA System: %02x\n", blah & 0xf);
+ if (debug & DEBUG_CARD) {
+ dev_info(&wc->vb.pdev->dev,
+ "VoiceDAA System: %02x\n", blah[1] & 0xf);
+ }
return 0;
}
@@ -2765,6 +2814,7 @@ wctdm_init_proslic(struct wctdm *wc, struct wctdm_module *const mod,
unsigned char r19,r9;
int x;
int fxsmode=0;
+ int addresses[NUM_CAL_REGS];
#if 0 /* TODO */
if (wc->mods[mod->card & 0xfc].type == QRV)
@@ -2883,7 +2933,10 @@ wctdm_init_proslic(struct wctdm *wc, struct wctdm_module *const mod,
/* Save calibration vectors */
for (x = 0; x < NUM_CAL_REGS; x++)
- fxs->calregs.vals[x] = wctdm_getreg(wc, mod, 96 + x);
+ addresses[x] = 96 + x;
+ wctdm_getregs(wc, mod, addresses, ARRAY_SIZE(addresses));
+ for (x = 0; x < NUM_CAL_REGS; x++)
+ fxs->calregs.vals[x] = addresses[x];
#endif
} else {