Compare commits

..

4 Commits

Author SHA1 Message Date
Shaun Ruffell
a951dd5e32 wcte43x: Do not reconfigure framer when span lineconfig is not changed.
If dahdi_span_ops.spanconfig is called multiple times in a row (like when
running dahdi_cfg; dahdi_cfg ) the tx signaling bits would go through a spurious
state that some far side devices would respond to.

Now, if the dahdi_span_ops.spanconfig callback is called, and the configuration
matches the existing configuration, we will not touch the framer.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-07-11 14:14:15 -05:00
Shaun Ruffell
8210fea5b3 wcte13xp: Do not reconfigure framer when span lineconfig is not changed.
If dahdi_span_ops.spanconfig is called multiple times in a row (like when
running dahdi_cfg; dahdi_cfg ) the tx signaling bits would go through a spurious
state that some far side devices would respond to.

Now, if the dahdi_span_ops.spanconfig callback is called, and the configuration
matches the existing configuration, we will not touch the framer.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-07-11 14:14:15 -05:00
Shaun Ruffell
a1ff3cb0c0 dahdi: Stop tones on channel when updating tone zone.
If a channel is currently playing a tone when the tone zone is updated, the
existing tone zone could be freed while the channel keeps a reference to the
current tone (curtone) that points into the freed zone.

If the newly freed tone is then modified, there was a window where it was
possible to  corrupt 'struct dahdi_chan' (by overrunning swritechunk[])
resulting in a "BUG: unable to handle kernel paging request at virtual address"
panic in the context of __dahdi_transmit_chunk().

Reported-and-Tested-by: Matt Behrens <matt@zigg.com>
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-07-07 12:25:36 -05:00
Shaun Ruffell
089b593b56 wct4xxp: Report rx signalling bit changes after spanconfig.
This fixes a long standing issue where, for CAS signaling, the RX bits were
sometimes misreported after span configuration before the first detected state
change.

The logic in the wct4xxp driver now matches that in the wcte43x driver and
wcte13xp drivers. The wcte12xp driver always polls the sigbits due to how
voicebus works and is not affected by this.

Internal-Issue-ID: DAHDI-1081
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2014-06-27 22:40:28 -05:00
4 changed files with 84 additions and 11 deletions

View File

@@ -1811,6 +1811,17 @@ static int start_tone(struct dahdi_chan *chan, int tone)
return res;
}
/**
* stop_tone - Stops any tones on a channel.
*
* Must be called with chan->lock held.
*
*/
static inline int stop_tone(struct dahdi_chan *chan)
{
return start_tone(chan, -1);
}
static int set_tone_zone(struct dahdi_chan *chan, int zone)
{
int res = 0;
@@ -1838,6 +1849,9 @@ static int set_tone_zone(struct dahdi_chan *chan, int zone)
return -ENODATA;
spin_lock_irqsave(&chan->lock, flags);
stop_tone(chan);
if (chan->curzone) {
struct dahdi_zone *zone = chan->curzone;
chan->curzone = NULL;

View File

@@ -3296,8 +3296,6 @@ static void t4_check_sigbits(struct t4 *wc, int span)
dev_notice(&wc->dev->dev, "Checking sigbits on span %d\n",
span + 1);
if (!(ts->span.flags & DAHDI_FLAG_RUNNING))
return;
if (E1 == ts->linemode) {
for (i = 0; i < 15; i++) {
a = t4_framer_in(wc, span, 0x71 + i);
@@ -3687,6 +3685,7 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
struct t4_span *ts = wc->tspans[span];
struct dahdi_chan *sigchan;
unsigned long flags;
bool recheck_sigbits = false;
/* 1st gen cards isn't used interrupts */
@@ -3712,6 +3711,8 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
ts->span.count.ebit += __t4_framer_in(wc, span, EBCL_T);
ts->span.count.be += __t4_framer_in(wc, span, BECL_T);
ts->span.count.prbs = __t4_framer_in(wc, span, FRS1_T);
if (DAHDI_RXSIG_INITIAL == ts->span.chans[0]->rxhooksig)
recheck_sigbits = true;
}
spin_unlock_irqrestore(&wc->reglock, flags);
@@ -3720,7 +3721,7 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
ts->span.count.errsec += 1;
}
if (isr0)
if (isr0 & 0x08 || recheck_sigbits)
t4_check_sigbits(wc, span);
if (E1 == ts->linemode) {

View File

@@ -110,6 +110,7 @@ struct t13x {
struct vpm450m *vpm;
struct mutex lock;
struct wcxb xb;
u32 lineconfig_fingerprint;
};
static void te13x_handle_transmit(struct wcxb *xb, void *vfp);
@@ -1675,12 +1676,37 @@ static void t13x_chan_set_sigcap(struct dahdi_span *span, int x)
}
}
static bool t13x_lineconfig_changed(struct t13x *wc,
const struct dahdi_lineconfig *lc)
{
unsigned long flags;
bool result;
u32 crc = crc32(~0, lc, sizeof(*lc));
spin_lock_irqsave(&wc->reglock, flags);
result = (crc != wc->lineconfig_fingerprint);
spin_unlock_irqrestore(&wc->reglock, flags);
return result;
}
static void t13x_save_lineconfig(struct t13x *wc,
const struct dahdi_lineconfig *lc)
{
unsigned long flags;
u32 crc = crc32(~0, lc, sizeof(*lc));
spin_lock_irqsave(&wc->reglock, flags);
wc->lineconfig_fingerprint = crc;
spin_unlock_irqrestore(&wc->reglock, flags);
}
static int
t13x_spanconfig(struct file *file, struct dahdi_span *span,
struct dahdi_lineconfig *lc)
{
struct t13x *wc = container_of(span, struct t13x, span);
int i;
int res = 0;
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
@@ -1693,10 +1719,13 @@ t13x_spanconfig(struct file *file, struct dahdi_span *span,
t13x_chan_set_sigcap(span, i);
/* If already running, apply changes immediately */
if (test_bit(DAHDI_FLAGBIT_RUNNING, &span->flags))
return t13x_startup(file, span);
return 0;
if (test_bit(DAHDI_FLAGBIT_RUNNING, &span->flags) &&
t13x_lineconfig_changed(wc, lc)) {
res = t13x_startup(file, span);
if (!res)
t13x_save_lineconfig(wc, lc);
}
return res;
}
/**

View File

@@ -110,6 +110,7 @@ struct t43x_span {
bool debounce;
int syncpos;
int sync;
u32 lineconfig_fingerprint;
};
struct t43x_clksrc_work {
@@ -2377,6 +2378,30 @@ static void t43x_chan_set_sigcap(struct dahdi_span *span, int x)
}
}
static bool t43x_lineconfig_changed(struct t43x_span *ts,
const struct dahdi_lineconfig *lc)
{
unsigned long flags;
bool result;
u32 crc = crc32(~0, lc, sizeof(*lc));
spin_lock_irqsave(&ts->owner->reglock, flags);
result = (crc != ts->lineconfig_fingerprint);
spin_unlock_irqrestore(&ts->owner->reglock, flags);
return result;
}
static void t43x_save_lineconfig(struct t43x_span *ts,
const struct dahdi_lineconfig *lc)
{
unsigned long flags;
u32 crc = crc32(~0, lc, sizeof(*lc));
spin_lock_irqsave(&ts->owner->reglock, flags);
ts->lineconfig_fingerprint = crc;
spin_unlock_irqrestore(&ts->owner->reglock, flags);
}
static int
t43x_spanconfig(struct file *file, struct dahdi_span *span,
struct dahdi_lineconfig *lc)
@@ -2384,6 +2409,7 @@ t43x_spanconfig(struct file *file, struct dahdi_span *span,
struct t43x_span *ts = container_of(span, struct t43x_span, span);
struct t43x *wc = ts->owner;
int i;
int res = 0;
if (debug)
dev_info(&wc->xb.pdev->dev, "%s\n", __func__);
@@ -2420,10 +2446,13 @@ t43x_spanconfig(struct file *file, struct dahdi_span *span,
t43x_chan_set_sigcap(span, i);
/* If already running, apply changes immediately */
if (test_bit(DAHDI_FLAGBIT_RUNNING, &span->flags))
return t43x_startup(file, span);
return 0;
if (test_bit(DAHDI_FLAGBIT_RUNNING, &span->flags) &&
t43x_lineconfig_changed(ts, lc)) {
res = t43x_startup(file, span);
if (!res)
t43x_save_lineconfig(ts, lc);
}
return res;
}
/*