wcte13xp: Do not get stuck in "Not Open" state when DAHDI_CONFIG_NOTOPEN is set.

If dahdi_cfg set the DAHDI_CONFIG_NOTOPEN setting on the span, which it does
when the "yellow" flag is added to the span config line, then it was possible
for the span to get stuck with DAHDI_ALARM_NOTOPEN (NOP).

This is because the wcte13xp driver only updates the alarm state when the framer
reports that the span alarm has changed. Therefore, unless the framer goes
through an alarm transition, the fact that channels are opened was never noticed
by alarm handling routine.

Now check the alarm state directly when the first channel is opened, and the
last channel is closed.

Internal-Issue-ID: DAHDI-1103
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
This commit is contained in:
Shaun Ruffell 2014-06-17 00:42:44 -05:00 committed by Russ Meyerriecks
parent b3a6b91858
commit f35e8aafb0
1 changed files with 60 additions and 9 deletions

View File

@ -92,9 +92,10 @@ struct t13x {
unsigned long loopuptimer;
unsigned long loopdntimer;
const char *name;
#define INITIALIZED 1
#define SHUTDOWN 2
#define READY 3
#define INITIALIZED 1
#define SHUTDOWN 2
#define READY 3
#define HAVE_OPEN_CHANNELS 4
unsigned long bit_flags;
u32 ledstate;
struct dahdi_device *ddev;
@ -1285,6 +1286,18 @@ static int te13xp_check_for_interrupts(struct t13x *wc)
return 0;
}
static bool have_open_channels(const struct t13x *wc)
{
int x, j;
for (x = 0, j = 0; x < wc->span.channels; x++) {
const struct dahdi_chan *chan = wc->span.chans[x];
if (test_bit(DAHDI_FLAGBIT_OPEN, &chan->flags) ||
dahdi_have_netdev(chan))
return true;
}
return false;
}
static int t13x_startup(struct file *file, struct dahdi_span *span)
{
struct t13x *wc = container_of(span, struct t13x, span);
@ -1315,6 +1328,12 @@ static int t13x_startup(struct file *file, struct dahdi_span *span)
dev_info(&wc->xb.pdev->dev,
"Calling startup (flags is %lu)\n", span->flags);
/* Check for "open channels" here in case some channels have netdev. */
if (have_open_channels(wc))
clear_bit(HAVE_OPEN_CHANNELS, &wc->bit_flags);
else
set_bit(HAVE_OPEN_CHANNELS, &wc->bit_flags);
/* Get this party started */
local_irq_save(flags);
t13x_check_alarms(wc);
@ -1904,7 +1923,6 @@ static void t13x_check_alarms(struct t13x *wc)
{
unsigned char c, d;
int alarms;
int x, j;
if (!(test_bit(DAHDI_FLAGBIT_RUNNING, &wc->span.flags)))
return;
@ -1943,11 +1961,7 @@ static void t13x_check_alarms(struct t13x *wc)
}
if (wc->span.lineconfig & DAHDI_CONFIG_NOTOPEN) {
for (x = 0, j = 0; x < wc->span.channels; x++)
if ((wc->span.chans[x]->flags & DAHDI_FLAG_OPEN) ||
dahdi_have_netdev(wc->span.chans[x]))
j++;
if (!j)
if (!test_bit(HAVE_OPEN_CHANNELS, &wc->bit_flags))
alarms |= DAHDI_ALARM_NOTOPEN;
else
alarms &= ~DAHDI_ALARM_NOTOPEN;
@ -2348,6 +2362,41 @@ static void te13xp_timer(unsigned long data)
static inline void create_sysfs_files(struct t13x *wc) { return; }
static inline void remove_sysfs_files(struct t13x *wc) { return; }
static int t13x_open(struct dahdi_chan *chan)
{
struct t13x *wc = chan->pvt;
unsigned long flags;
if (!(wc->span.lineconfig & DAHDI_CONFIG_NOTOPEN))
return 0;
if (!test_and_set_bit(HAVE_OPEN_CHANNELS, &wc->bit_flags)) {
local_irq_save(flags);
t13x_check_alarms(wc);
local_irq_restore(flags);
}
return 0;
}
static int t13x_close(struct dahdi_chan *chan)
{
struct t13x *wc = chan->pvt;
unsigned long flags;
if (!(wc->span.lineconfig & DAHDI_CONFIG_NOTOPEN))
return 0;
if (!have_open_channels(wc)) {
if (test_and_clear_bit(HAVE_OPEN_CHANNELS, &wc->bit_flags)) {
local_irq_save(flags);
t13x_check_alarms(wc);
local_irq_restore(flags);
}
}
return 0;
}
static const struct dahdi_span_ops t13x_span_ops = {
.owner = THIS_MODULE,
.spanconfig = t13x_spanconfig,
@ -2359,6 +2408,8 @@ static const struct dahdi_span_ops t13x_span_ops = {
.set_spantype = t13x_set_linemode,
.echocan_create = t13x_echocan_create,
.echocan_name = t13x_echocan_name,
.open = t13x_open,
.close = t13x_close,
};
#define SPI_BASE 0x200