From ba8abe97cc5a1d7973284b254ef9f336d0bdf49e Mon Sep 17 00:00:00 2001 From: Shaun Ruffell Date: Mon, 14 Feb 2011 22:37:19 -0600 Subject: wctdm24xxp: Hold the reglock longer in the interrupt handler. Cuts down on the overhead of constantly saving and restoring the interrupt registers. Signed-off-by: Shaun Ruffell --- drivers/dahdi/voicebus/GpakCust.h | 20 +++---- drivers/dahdi/wctdm24xxp/base.c | 108 ++++++++++++++++++++------------------ 2 files changed, 68 insertions(+), 60 deletions(-) diff --git a/drivers/dahdi/voicebus/GpakCust.h b/drivers/dahdi/voicebus/GpakCust.h index 83968e5..c9765c0 100644 --- a/drivers/dahdi/voicebus/GpakCust.h +++ b/drivers/dahdi/voicebus/GpakCust.h @@ -154,38 +154,38 @@ void vpmadt032_echocan_free(struct vpmadt032 *vpm, int channo, struct GpakEcanParms; void vpmadt032_get_default_parameters(struct GpakEcanParms *p); -/* If there is a command ready to go to the VPMADT032, return it, otherwise NULL */ +/* If there is a command ready to go to the VPMADT032, return it, otherwise + * NULL. Call with local interrupts disabled. */ static inline struct vpmadt032_cmd *vpmadt032_get_ready_cmd(struct vpmadt032 *vpm) { - unsigned long flags; struct vpmadt032_cmd *cmd; - spin_lock_irqsave(&vpm->list_lock, flags); + spin_lock(&vpm->list_lock); if (list_empty(&vpm->pending_cmds)) { - spin_unlock_irqrestore(&vpm->list_lock, flags); + spin_unlock(&vpm->list_lock); return NULL; } cmd = list_entry(vpm->pending_cmds.next, struct vpmadt032_cmd, node); list_move_tail(&cmd->node, &vpm->active_cmds); - spin_unlock_irqrestore(&vpm->list_lock, flags); + spin_unlock(&vpm->list_lock); return cmd; } +/** + * call with local interrupts disabled. + */ static inline void vpmadt032_resend(struct vpmadt032 *vpm) { - unsigned long flags; struct vpmadt032_cmd *cmd, *temp; - BUG_ON(!vpm); - /* By moving the commands back to the pending list, they will be * transmitted when room is available */ - spin_lock_irqsave(&vpm->list_lock, flags); + spin_lock(&vpm->list_lock); list_for_each_entry_safe(cmd, temp, &vpm->active_cmds, node) { cmd->desc &= ~(__VPM150M_TX); list_move_tail(&cmd->node, &vpm->pending_cmds); } - spin_unlock_irqrestore(&vpm->list_lock, flags); + spin_unlock(&vpm->list_lock); } diff --git a/drivers/dahdi/wctdm24xxp/base.c b/drivers/dahdi/wctdm24xxp/base.c index 58efb7d..78275fd 100644 --- a/drivers/dahdi/wctdm24xxp/base.c +++ b/drivers/dahdi/wctdm24xxp/base.c @@ -474,9 +474,8 @@ static inline bool is_good_frame(const u8 *sframe) return a != b; } -static inline void cmd_dequeue_vpmadt032(struct wctdm *wc, u8 *eframe) +static void cmd_dequeue_vpmadt032(struct wctdm *wc, u8 *eframe) { - unsigned long flags; struct vpmadt032_cmd *curcmd = NULL; struct vpmadt032 *vpmadt032 = wc->vpmadt032; int x; @@ -488,7 +487,6 @@ static inline void cmd_dequeue_vpmadt032(struct wctdm *wc, u8 *eframe) if (test_bit(VPM150M_HPIRESET, &vpmadt032->control)) { if (debug & DEBUG_ECHOCAN) dev_info(&wc->vb.pdev->dev, "HW Resetting VPMADT032...\n"); - spin_lock_irqsave(&wc->reglock, flags); for (x = 24; x < 28; x++) { if (x == 24) { if (test_and_clear_bit(VPM150M_HPIRESET, @@ -503,7 +501,6 @@ static inline void cmd_dequeue_vpmadt032(struct wctdm *wc, u8 *eframe) eframe[CMD_BYTE(x, 1, 0)] = 0; eframe[CMD_BYTE(x, 2, 0)] = 0x00; } - spin_unlock_irqrestore(&wc->reglock, flags); return; } @@ -587,10 +584,9 @@ static inline void cmd_dequeue_vpmadt032(struct wctdm *wc, u8 *eframe) } } -static inline void cmd_dequeue(struct wctdm *wc, unsigned char *eframe, int card, int pos) +static void _cmd_dequeue(struct wctdm *wc, u8 *eframe, int card, int pos) { struct wctdm_module *const mod = &wc->mods[card]; - unsigned long flags; unsigned int curcmd=0; int x; int subaddr = card & 0x3; @@ -604,7 +600,6 @@ static inline void cmd_dequeue(struct wctdm *wc, unsigned char *eframe, int card /* Skip audio */ eframe += 24; - spin_lock_irqsave(&wc->reglock, flags); /* Search for something waiting to transmit */ if (pos) { for (x = 0; x < MAX_COMMANDS; x++) { @@ -619,25 +614,36 @@ static inline void cmd_dequeue(struct wctdm *wc, unsigned char *eframe, int card if (!curcmd) { /* If nothing else, use filler */ - if (mod->type == FXS) + switch (mod->type) { + case FXS: curcmd = CMD_RD(LINE_STATE); - else if (mod->type == FXO) + break; + case FXO: curcmd = CMD_RD(12); - else if (mod->type == BRI) + break; + case BRI: curcmd = 0x101010; - else if (mod->type == QRV) + break; + case QRV: curcmd = CMD_RD(3); + break; + default: + break; + } } - if (mod->type == FXS) { + switch (mod->type) { + case FXS: eframe[CMD_BYTE(card, 0, mod->altcs)] = (1 << (subaddr)); if (curcmd & __CMD_WR) eframe[CMD_BYTE(card, 1, mod->altcs)] = (curcmd >> 8) & 0x7f; else eframe[CMD_BYTE(card, 1, mod->altcs)] = 0x80 | ((curcmd >> 8) & 0x7f); eframe[CMD_BYTE(card, 2, mod->altcs)] = curcmd & 0xff; + break; - } else if (mod->type == FXO) { + case FXO: + { static const int FXO_ADDRS[4] = { 0x00, 0x08, 0x04, 0x0c }; int idx = CMD_BYTE(card, 0, mod->altcs); if (curcmd & __CMD_WR) @@ -646,8 +652,9 @@ static inline void cmd_dequeue(struct wctdm *wc, unsigned char *eframe, int card eframe[idx] = 0x60 | FXO_ADDRS[subaddr]; eframe[CMD_BYTE(card, 1, mod->altcs)] = (curcmd >> 8) & 0xff; eframe[CMD_BYTE(card, 2, mod->altcs)] = curcmd & 0xff; - - } else if (mod->type == FXSINIT) { + break; + } + case FXSINIT: /* Special case, we initialize the FXS's into the three-byte command mode then switch to the regular mode. To send it into thee byte mode, treat the path as 6 two-byte commands and in the last one we initialize register 0 to 0x80. All modules @@ -658,18 +665,18 @@ static inline void cmd_dequeue(struct wctdm *wc, unsigned char *eframe, int card eframe[CMD_BYTE(card, 2, mod->altcs)] = 0x80; else eframe[CMD_BYTE(card, 2, mod->altcs)] = 0x00; + break; - } else if (mod->type == BRI) { - + case BRI: if (unlikely((curcmd != 0x101010) && (curcmd & 0x1010) == 0x1010)) /* b400m CPLD */ eframe[CMD_BYTE(card, 0, 0)] = 0x55; else /* xhfc */ eframe[CMD_BYTE(card, 0, 0)] = 0x10; eframe[CMD_BYTE(card, 1, 0)] = (curcmd >> 8) & 0xff; eframe[CMD_BYTE(card, 2, 0)] = curcmd & 0xff; + break; - } else if (mod->type == QRV) { - + case QRV: eframe[CMD_BYTE(card, 0, mod->altcs)] = 0x00; if (!curcmd) { eframe[CMD_BYTE(card, 1, mod->altcs)] = 0x00; @@ -681,18 +688,19 @@ static inline void cmd_dequeue(struct wctdm *wc, unsigned char *eframe, int card eframe[CMD_BYTE(card, 1, mod->altcs)] = 0xc0 | ((curcmd >> 8) & 0x3f); eframe[CMD_BYTE(card, 2, mod->altcs)] = curcmd & 0xff; } - } else if (mod->type == NONE) { + break; + + case NONE: eframe[CMD_BYTE(card, 0, mod->altcs)] = 0x10; eframe[CMD_BYTE(card, 1, mod->altcs)] = 0x10; eframe[CMD_BYTE(card, 2, mod->altcs)] = 0x10; + break; } - spin_unlock_irqrestore(&wc->reglock, flags); } static inline void cmd_decipher_vpmadt032(struct wctdm *wc, const u8 *eframe) { - unsigned long flags; - struct vpmadt032 *vpm = wc->vpmadt032; + struct vpmadt032 *const vpm = wc->vpmadt032; struct vpmadt032_cmd *cmd; BUG_ON(!vpm); @@ -703,18 +711,17 @@ static inline void cmd_decipher_vpmadt032(struct wctdm *wc, const u8 *eframe) return; } - spin_lock_irqsave(&vpm->list_lock, flags); + spin_lock(&vpm->list_lock); cmd = list_entry(vpm->active_cmds.next, struct vpmadt032_cmd, node); if (wc->rxident == cmd->txident) { list_del_init(&cmd->node); } else { cmd = NULL; } - spin_unlock_irqrestore(&vpm->list_lock, flags); + spin_unlock(&vpm->list_lock); - if (!cmd) { + if (!cmd) return; - } /* Skip audio */ eframe += 24; @@ -730,10 +737,12 @@ static inline void cmd_decipher_vpmadt032(struct wctdm *wc, const u8 *eframe) } } -static inline void cmd_decipher(struct wctdm *wc, const u8 *eframe, int card) +/** + * Call with the reglock held and local interrupts disabled + */ +static void _cmd_decipher(struct wctdm *wc, const u8 *eframe, int card) { struct wctdm_module *const mod = &wc->mods[card]; - unsigned long flags; unsigned char ident; int x; @@ -743,7 +752,6 @@ static inline void cmd_decipher(struct wctdm *wc, const u8 *eframe, int card) /* Skip audio */ eframe += 24; - spin_lock_irqsave(&wc->reglock, flags); /* Search for any pending results */ for (x=0;xreglock, flags); } static void cmd_checkisr(struct wctdm *wc, struct wctdm_module *const mod) @@ -857,7 +864,8 @@ static void insert_tdm_data(const struct wctdm *wc, u8 *sframe) static inline void wctdm_transmitprep(struct wctdm *wc, unsigned char *sframe) { - int x,y; + unsigned long flags; + int x, y; struct dahdi_span *s; unsigned char *eframe = sframe; @@ -879,6 +887,7 @@ static inline void wctdm_transmitprep(struct wctdm *wc, unsigned char *sframe) #endif } + spin_lock_irqsave(&wc->reglock, flags); for (x = 0; x < DAHDI_CHUNKSIZE; x++) { /* Send a sample, as a 32-bit word */ @@ -887,12 +896,11 @@ static inline void wctdm_transmitprep(struct wctdm *wc, unsigned char *sframe) * BRI modules have a different number of TDM channels than * installed modules. */ for (y = 0; y < wc->avchannels; y++) { - if (!x && y < wc->mods_per_board) { + if (!x && y < wc->mods_per_board) cmd_checkisr(wc, &wc->mods[y]); - } if (y < wc->mods_per_board) - cmd_dequeue(wc, eframe, y, x); + _cmd_dequeue(wc, eframe, y, x); } if (wc->vpmadt032) { @@ -909,6 +917,7 @@ static inline void wctdm_transmitprep(struct wctdm *wc, unsigned char *sframe) } eframe += (EFRAME_SIZE + EFRAME_GAP); } + spin_unlock_irqrestore(&wc->reglock, flags); } static bool @@ -1009,12 +1018,13 @@ int wctdm_getreg(struct wctdm *wc, struct wctdm_module *const mod, int addr) return val; } -static inline void cmd_retransmit(struct wctdm *wc) +/** + * call with wc->reglock held and interrupts disabled. + */ +static void cmd_retransmit(struct wctdm *wc) { int x,y; - unsigned long flags; /* Force retransmissions */ - spin_lock_irqsave(&wc->reglock, flags); for (x=0;xmods_per_board; y++) { struct wctdm_module *const mod = &wc->mods[y]; @@ -1024,7 +1034,6 @@ static inline void cmd_retransmit(struct wctdm *wc) mod->cmdq.cmds[x] &= ~(__CMD_TX | (0xff << 24)); } } - spin_unlock_irqrestore(&wc->reglock, flags); #ifdef VPM_SUPPORT if (wc->vpmadt032) vpmadt032_resend(wc->vpmadt032); @@ -1085,8 +1094,9 @@ static void extract_tdm_data(struct wctdm *wc, const u8 *sframe) static inline void wctdm_receiveprep(struct wctdm *wc, const u8 *sframe) { - int x,y; - bool irqmiss = 0; + unsigned long flags; + int x, y; + bool irqmiss = false; unsigned char expected; const u8 *eframe = sframe; @@ -1096,27 +1106,25 @@ static inline void wctdm_receiveprep(struct wctdm *wc, const u8 *sframe) if (likely(wc->initialized)) extract_tdm_data(wc, sframe); + spin_lock_irqsave(&wc->reglock, flags); for (x = 0; x < DAHDI_CHUNKSIZE; x++) { if (x < DAHDI_CHUNKSIZE - 1) { - expected = wc->rxident+1; + expected = wc->rxident + 1; wc->rxident = eframe[EFRAME_SIZE + 1]; if (wc->rxident != expected) { - irqmiss = 1; + irqmiss = true; cmd_retransmit(wc); } } - for (y = 0; y < wc->avchannels; y++) { - cmd_decipher(wc, eframe, y); - } - if (wc->vpmadt032) { - cmd_decipher_vpmadt032(wc, eframe); - } else if (wc->vpmadt032) { + for (y = 0; y < wc->avchannels; y++) + _cmd_decipher(wc, eframe, y); + if (wc->vpmadt032) cmd_decipher_vpmadt032(wc, eframe); - } eframe += (EFRAME_SIZE + EFRAME_GAP); } + spin_unlock_irqrestore(&wc->reglock, flags); /* XXX We're wasting 8 taps. We should get closer :( */ if (likely(wc->initialized)) { -- cgit v1.2.3