summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2011-02-14 22:37:19 -0600
committerShaun Ruffell <sruffell@digium.com>2011-04-15 14:18:59 -0500
commitba8abe97cc5a1d7973284b254ef9f336d0bdf49e (patch)
tree741bd28d138470561bff2291d832f5bae6e2c99f
parent4043efcbb5da2c08f9658345ab48e8a4ea720d12 (diff)
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 <sruffell@digium.com>
-rw-r--r--drivers/dahdi/voicebus/GpakCust.h20
-rw-r--r--drivers/dahdi/wctdm24xxp/base.c108
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;x<MAX_COMMANDS;x++) {
@@ -767,7 +775,6 @@ static inline void cmd_decipher(struct wctdm *wc, const u8 *eframe, int card)
}
}
}
- spin_unlock_irqrestore(&wc->reglock, 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;x<MAX_COMMANDS;x++) {
for (y = 0; y < wc->mods_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)) {