From 5c29fda4c36404268b665d1248f3d8006ca6994c Mon Sep 17 00:00:00 2001 From: Shaun Ruffell Date: Fri, 11 Mar 2011 15:15:40 -0600 Subject: 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 --- drivers/dahdi/wctdm24xxp/base.c | 75 +++++++++++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 11 deletions(-) (limited to 'drivers') 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 { -- cgit v1.2.3