dahdi: Fixed loopup/loopdown signals
The loopup/loopdown T1 maintenance feature in the single through quad-span drivers now function properly, according to AT&T TR54016, by sending a full rate pattern down the line. T1.403 ESF/Data Link patterns are not supported currently. Also grouped all the maint reset register clears under a single irq lock to crank the performance up past 11. Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com> Acked-by: Shaun Ruffell <sruffell@digium.com> Acked-by: Kinsey Moore <kmoore@digium.com> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9516 a0bf4364-ded3-4de4-8d8a-66a801d63aff
This commit is contained in:
parent
bbdcb0c7ba
commit
6e25ac61db
@ -472,6 +472,10 @@ static void t4_check_sigbits(struct t4 *wc, int span);
|
|||||||
#define FMR0_SIM (1 << 0) /* Alarm Simulation */
|
#define FMR0_SIM (1 << 0) /* Alarm Simulation */
|
||||||
#define FMR1_T 0x1D /* Framer Mode Register 1 */
|
#define FMR1_T 0x1D /* Framer Mode Register 1 */
|
||||||
#define FMR1_ECM (1 << 2) /* Error Counter 1sec Interrupt Enable */
|
#define FMR1_ECM (1 << 2) /* Error Counter 1sec Interrupt Enable */
|
||||||
|
#define FMR5 0x21 /* Framer Mode Register 5 */
|
||||||
|
#define FMR5_XLU (1 << 4) /* Transmit loopup code */
|
||||||
|
#define FMR5_XLD (1 << 5) /* Transmit loopdown code */
|
||||||
|
#define FMR5_EIBR (1 << 6) /* Internal Bit Robbing Access */
|
||||||
#define DEC_T 0x60 /* Diable Error Counter */
|
#define DEC_T 0x60 /* Diable Error Counter */
|
||||||
#define IERR_T 0x1B /* Single Bit Defect Insertion Register */
|
#define IERR_T 0x1B /* Single Bit Defect Insertion Register */
|
||||||
#define IBV 0 /* Bipolar violation */
|
#define IBV 0 /* Bipolar violation */
|
||||||
@ -1602,12 +1606,20 @@ static int t4_maint(struct dahdi_span *span, int cmd)
|
|||||||
case DAHDI_MAINT_LOOPUP:
|
case DAHDI_MAINT_LOOPUP:
|
||||||
dev_info(&wc->dev->dev, "Transmitting loopup code\n");
|
dev_info(&wc->dev->dev, "Transmitting loopup code\n");
|
||||||
t4_clear_maint(span);
|
t4_clear_maint(span);
|
||||||
t4_framer_out(wc, span->offset, 0x21, 0x50);
|
spin_lock_irqsave(&wc->reglock, flags);
|
||||||
|
reg = __t4_framer_in(wc, span->offset, FMR5);
|
||||||
|
__t4_framer_out(wc, span->offset, FMR5, (reg|FMR5_XLU));
|
||||||
|
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||||
|
ts->span.maintstat = DAHDI_MAINT_REMOTELOOP;
|
||||||
break;
|
break;
|
||||||
case DAHDI_MAINT_LOOPDOWN:
|
case DAHDI_MAINT_LOOPDOWN:
|
||||||
dev_info(&wc->dev->dev, "Transmitting loopdown code\n");
|
dev_info(&wc->dev->dev, "Transmitting loopdown code\n");
|
||||||
t4_clear_maint(span);
|
t4_clear_maint(span);
|
||||||
t4_framer_out(wc, span->offset, 0x21, 0x60);
|
spin_lock_irqsave(&wc->reglock, flags);
|
||||||
|
reg = __t4_framer_in(wc, span->offset, FMR5);
|
||||||
|
__t4_framer_out(wc, span->offset, FMR5, (reg|FMR5_XLD));
|
||||||
|
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||||
|
ts->span.maintstat = DAHDI_MAINT_NONE;
|
||||||
break;
|
break;
|
||||||
case DAHDI_MAINT_FAS_DEFECT:
|
case DAHDI_MAINT_FAS_DEFECT:
|
||||||
t4_framer_out(wc, span->offset, IERR_T, IFASE);
|
t4_framer_out(wc, span->offset, IERR_T, IFASE);
|
||||||
@ -1686,23 +1698,32 @@ static int t4_clear_maint(struct dahdi_span *span)
|
|||||||
struct t4_span *ts = container_of(span, struct t4_span, span);
|
struct t4_span *ts = container_of(span, struct t4_span, span);
|
||||||
struct t4 *wc = ts->owner;
|
struct t4 *wc = ts->owner;
|
||||||
unsigned int reg;
|
unsigned int reg;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&wc->reglock, flags);
|
||||||
|
|
||||||
/* Clear local loop */
|
/* Clear local loop */
|
||||||
reg = t4_framer_in(wc, span->offset, LIM0_T);
|
reg = __t4_framer_in(wc, span->offset, LIM0_T);
|
||||||
t4_framer_out(wc, span->offset, LIM0_T, (reg & ~LIM0_LL));
|
__t4_framer_out(wc, span->offset, LIM0_T, (reg & ~LIM0_LL));
|
||||||
|
|
||||||
/* Clear Remote Loop */
|
/* Clear Remote Loop */
|
||||||
reg = t4_framer_in(wc, span->offset, LIM1_T);
|
reg = __t4_framer_in(wc, span->offset, LIM1_T);
|
||||||
t4_framer_out(wc, span->offset, LIM1_T, (reg & ~LIM1_RL));
|
__t4_framer_out(wc, span->offset, LIM1_T, (reg & ~LIM1_RL));
|
||||||
|
|
||||||
/* Clear Remote Payload Loop */
|
/* Clear Remote Payload Loop */
|
||||||
reg = t4_framer_in(wc, span->offset, FMR2_T);
|
reg = __t4_framer_in(wc, span->offset, FMR2_T);
|
||||||
t4_framer_out(wc, span->offset, FMR2_T, (reg & ~FMR2_PLB));
|
__t4_framer_out(wc, span->offset, FMR2_T, (reg & ~FMR2_PLB));
|
||||||
|
|
||||||
/* Clear PRBS */
|
/* Clear PRBS */
|
||||||
reg = t4_framer_in(wc, span->offset, LCR1_T);
|
reg = __t4_framer_in(wc, span->offset, LCR1_T);
|
||||||
t4_framer_out(wc, span->offset, LCR1_T, (reg & ~(XPRBS | EPRM)));
|
__t4_framer_out(wc, span->offset, LCR1_T, (reg & ~(XPRBS | EPRM)));
|
||||||
|
|
||||||
|
/* Clear loopup/loopdown signals on the line */
|
||||||
|
reg = __t4_framer_in(wc, span->offset, FMR5);
|
||||||
|
__t4_framer_out(wc, span->offset, FMR5, (reg & ~(FMR5_XLU | FMR5_XLD)));
|
||||||
|
span->maintstat = DAHDI_MAINT_NONE;
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||||
span->mainttimer = 0;
|
span->mainttimer = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -2489,7 +2510,7 @@ static void __t4_configure_t1(struct t4 *wc, int unit, int lineconfig, int txlev
|
|||||||
}
|
}
|
||||||
__t4_framer_out(wc, unit, 0x1c, fmr0);
|
__t4_framer_out(wc, unit, 0x1c, fmr0);
|
||||||
__t4_framer_out(wc, unit, 0x20, fmr4);
|
__t4_framer_out(wc, unit, 0x20, fmr4);
|
||||||
__t4_framer_out(wc, unit, 0x21, 0x40); /* FMR5: Enable RBS mode */
|
__t4_framer_out(wc, unit, FMR5, FMR5_EIBR); /* FMR5: Enable RBS mode */
|
||||||
|
|
||||||
__t4_framer_out(wc, unit, 0x37, 0xf0 ); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */
|
__t4_framer_out(wc, unit, 0x37, 0xf0 ); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */
|
||||||
__t4_framer_out(wc, unit, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */
|
__t4_framer_out(wc, unit, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */
|
||||||
@ -3130,6 +3151,10 @@ static void t4_check_alarms(struct t4 *wc, int span)
|
|||||||
if ((!ts->span.mainttimer) && (d & 0x08)) {
|
if ((!ts->span.mainttimer) && (d & 0x08)) {
|
||||||
/* Loop-up code detected */
|
/* Loop-up code detected */
|
||||||
if ((ts->loopupcnt++ > 80) && (ts->span.maintstat != DAHDI_MAINT_REMOTELOOP)) {
|
if ((ts->loopupcnt++ > 80) && (ts->span.maintstat != DAHDI_MAINT_REMOTELOOP)) {
|
||||||
|
dev_notice(&wc->dev->dev,
|
||||||
|
"span %d: Loopup detected,"\
|
||||||
|
" enabling remote loop\n",
|
||||||
|
span+1);
|
||||||
__t4_framer_out(wc, span, 0x36, 0x08); /* LIM0: Disable any local loop */
|
__t4_framer_out(wc, span, 0x36, 0x08); /* LIM0: Disable any local loop */
|
||||||
__t4_framer_out(wc, span, 0x37, 0xf6 ); /* LIM1: Enable remote loop */
|
__t4_framer_out(wc, span, 0x37, 0xf6 ); /* LIM1: Enable remote loop */
|
||||||
ts->span.maintstat = DAHDI_MAINT_REMOTELOOP;
|
ts->span.maintstat = DAHDI_MAINT_REMOTELOOP;
|
||||||
@ -3140,6 +3165,10 @@ static void t4_check_alarms(struct t4 *wc, int span)
|
|||||||
if ((!ts->span.mainttimer) && (d & 0x10)) {
|
if ((!ts->span.mainttimer) && (d & 0x10)) {
|
||||||
/* Loop-down code detected */
|
/* Loop-down code detected */
|
||||||
if ((ts->loopdowncnt++ > 80) && (ts->span.maintstat == DAHDI_MAINT_REMOTELOOP)) {
|
if ((ts->loopdowncnt++ > 80) && (ts->span.maintstat == DAHDI_MAINT_REMOTELOOP)) {
|
||||||
|
dev_notice(&wc->dev->dev,
|
||||||
|
"span %d: Loopdown detected,"\
|
||||||
|
" disabling remote loop\n",
|
||||||
|
span+1);
|
||||||
__t4_framer_out(wc, span, 0x36, 0x08); /* LIM0: Disable any local loop */
|
__t4_framer_out(wc, span, 0x36, 0x08); /* LIM0: Disable any local loop */
|
||||||
__t4_framer_out(wc, span, 0x37, 0xf0 ); /* LIM1: Disable remote loop */
|
__t4_framer_out(wc, span, 0x37, 0xf0 ); /* LIM1: Disable remote loop */
|
||||||
ts->span.maintstat = DAHDI_MAINT_NONE;
|
ts->span.maintstat = DAHDI_MAINT_NONE;
|
||||||
@ -3389,7 +3418,7 @@ static inline void __handle_leds(struct t4 *wc)
|
|||||||
static inline void t4_framer_interrupt(struct t4 *wc, int span)
|
static inline void t4_framer_interrupt(struct t4 *wc, int span)
|
||||||
{
|
{
|
||||||
/* Check interrupts for a given span */
|
/* Check interrupts for a given span */
|
||||||
unsigned char gis, isr0, isr1, isr2, isr3, isr4, reg;
|
unsigned char gis, isr0, isr1, isr2, isr3, isr4;
|
||||||
int readsize = -1;
|
int readsize = -1;
|
||||||
struct t4_span *ts = wc->tspans[span];
|
struct t4_span *ts = wc->tspans[span];
|
||||||
struct dahdi_chan *sigchan;
|
struct dahdi_chan *sigchan;
|
||||||
@ -3425,16 +3454,6 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
|
|||||||
ts->span.count.errsec += 1;
|
ts->span.count.errsec += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isr3 & 0x08) {
|
|
||||||
reg = t4_framer_in(wc, span, FRS1_T);
|
|
||||||
dev_info(&wc->dev->dev, "FRS1: %d\n", reg);
|
|
||||||
if (reg & LLBDD) {
|
|
||||||
dev_info(&wc->dev->dev, "Line loop-back activation "\
|
|
||||||
"signal detected with status: %01d "\
|
|
||||||
"for span %d\n", reg & LLBAD, span+1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isr0)
|
if (isr0)
|
||||||
t4_check_sigbits(wc, span);
|
t4_check_sigbits(wc, span);
|
||||||
|
|
||||||
|
@ -1281,6 +1281,9 @@ static int t1xxp_clear_maint(struct dahdi_span *span)
|
|||||||
if (reg < 0)
|
if (reg < 0)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
t1_setreg(wc, LIM1, reg & ~(LIM1_RL | LIM1_JATT));
|
t1_setreg(wc, LIM1, reg & ~(LIM1_RL | LIM1_JATT));
|
||||||
|
|
||||||
|
/* Clear loopup/loopdown signals on the line */
|
||||||
|
t1_setreg(wc, 0x21, 0x40);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1699,6 +1702,8 @@ static inline void t1_check_alarms(struct t1 *wc)
|
|||||||
if ((!wc->span.mainttimer) && (d & 0x08)) {
|
if ((!wc->span.mainttimer) && (d & 0x08)) {
|
||||||
/* Loop-up code detected */
|
/* Loop-up code detected */
|
||||||
if ((wc->loopupcnt++ > 80) && (wc->span.maintstat != DAHDI_MAINT_REMOTELOOP)) {
|
if ((wc->loopupcnt++ > 80) && (wc->span.maintstat != DAHDI_MAINT_REMOTELOOP)) {
|
||||||
|
t1_notice(wc, "Loopup detected,"\
|
||||||
|
" enabling remote loop\n");
|
||||||
t1_setreg(wc, 0x36, 0x08); /* LIM0: Disable any local loop */
|
t1_setreg(wc, 0x36, 0x08); /* LIM0: Disable any local loop */
|
||||||
t1_setreg(wc, 0x37, 0xf6); /* LIM1: Enable remote loop */
|
t1_setreg(wc, 0x37, 0xf6); /* LIM1: Enable remote loop */
|
||||||
wc->span.maintstat = DAHDI_MAINT_REMOTELOOP;
|
wc->span.maintstat = DAHDI_MAINT_REMOTELOOP;
|
||||||
@ -1709,6 +1714,8 @@ static inline void t1_check_alarms(struct t1 *wc)
|
|||||||
if ((!wc->span.mainttimer) && (d & 0x10)) {
|
if ((!wc->span.mainttimer) && (d & 0x10)) {
|
||||||
/* Loop-down code detected */
|
/* Loop-down code detected */
|
||||||
if ((wc->loopdowncnt++ > 80) && (wc->span.maintstat == DAHDI_MAINT_REMOTELOOP)) {
|
if ((wc->loopdowncnt++ > 80) && (wc->span.maintstat == DAHDI_MAINT_REMOTELOOP)) {
|
||||||
|
t1_notice(wc, "Loopdown detected,"\
|
||||||
|
" disabling remote loop\n");
|
||||||
t1_setreg(wc, 0x36, 0x08); /* LIM0: Disable any local loop */
|
t1_setreg(wc, 0x36, 0x08); /* LIM0: Disable any local loop */
|
||||||
t1_setreg(wc, 0x37, 0xf0); /* LIM1: Disable remote loop */
|
t1_setreg(wc, 0x37, 0xf0); /* LIM1: Disable remote loop */
|
||||||
wc->span.maintstat = DAHDI_MAINT_NONE;
|
wc->span.maintstat = DAHDI_MAINT_NONE;
|
||||||
|
@ -142,6 +142,9 @@ struct t1 {
|
|||||||
#define t1_info(t1, format, arg...) \
|
#define t1_info(t1, format, arg...) \
|
||||||
dev_info(&t1->vb.pdev->dev , format , ## arg)
|
dev_info(&t1->vb.pdev->dev , format , ## arg)
|
||||||
|
|
||||||
|
#define t1_notice(t1, format, arg...) \
|
||||||
|
dev_notice(&t1->vb.pdev->dev , format , ## arg)
|
||||||
|
|
||||||
/* Maintenance Mode Registers */
|
/* Maintenance Mode Registers */
|
||||||
#define LIM0 0x36
|
#define LIM0 0x36
|
||||||
#define LIM0_LL (1<<1)
|
#define LIM0_LL (1<<1)
|
||||||
|
Loading…
Reference in New Issue
Block a user