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> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9962 a0bf4364-ded3-4de4-8d8a-66a801d63aff
This commit is contained in:
parent
fca9c4949f
commit
8e96b99bc9
@ -152,38 +152,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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -484,7 +484,6 @@ static inline bool is_good_frame(const u8 *sframe)
|
||||
|
||||
static inline void cmd_dequeue_vpmadt032(struct wctdm *wc, u8 *eframe)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct vpmadt032_cmd *curcmd = NULL;
|
||||
struct vpmadt032 *vpmadt032 = wc->vpmadt032;
|
||||
int x;
|
||||
@ -496,7 +495,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,
|
||||
@ -511,7 +509,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;
|
||||
}
|
||||
|
||||
@ -595,10 +592,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;
|
||||
@ -612,7 +608,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++) {
|
||||
@ -627,25 +622,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)
|
||||
@ -654,8 +660,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
|
||||
@ -666,18 +673,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;
|
||||
@ -689,18 +696,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);
|
||||
@ -711,18 +719,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;
|
||||
@ -738,10 +745,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;
|
||||
|
||||
@ -751,7 +760,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++) {
|
||||
@ -775,7 +783,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)
|
||||
@ -865,7 +872,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;
|
||||
|
||||
@ -887,6 +895,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 */
|
||||
|
||||
@ -896,7 +905,7 @@ static inline void wctdm_transmitprep(struct wctdm *wc, unsigned char *sframe)
|
||||
* installed modules. */
|
||||
for (y = 0; y < wc->avchannels; y++) {
|
||||
if (y < wc->mods_per_board)
|
||||
cmd_dequeue(wc, eframe, y, x);
|
||||
_cmd_dequeue(wc, eframe, y, x);
|
||||
}
|
||||
|
||||
if (wc->vpmadt032) {
|
||||
@ -913,6 +922,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
|
||||
@ -1013,12 +1023,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];
|
||||
@ -1028,7 +1039,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);
|
||||
@ -1089,8 +1099,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;
|
||||
|
||||
@ -1100,27 +1111,26 @@ 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) {
|
||||
for (y = 0; y < wc->avchannels; y++)
|
||||
_cmd_decipher(wc, eframe, y);
|
||||
|
||||
if (wc->vpmadt032)
|
||||
cmd_decipher_vpmadt032(wc, eframe);
|
||||
} else 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)) {
|
||||
|
Loading…
Reference in New Issue
Block a user