From 71867c3de734f6d556ea66b67c25216c9a477a84 Mon Sep 17 00:00:00 2001 From: Shaun Ruffell Date: Tue, 17 Jun 2014 10:34:00 -0500 Subject: [PATCH] wcte43x: Do not get stuck in "Not Open" state when DAHDI_CONFIG_NOTOPEN is set. This is the same change for the wcte13xp driver but applied to the other xbus-based digital card. 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 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 Signed-off-by: Russ Meyerriecks --- drivers/dahdi/wcte43x-base.c | 79 +++++++++++++++++++++++++++++++----- 1 file changed, 68 insertions(+), 11 deletions(-) diff --git a/drivers/dahdi/wcte43x-base.c b/drivers/dahdi/wcte43x-base.c index 38dbbf7..ab9ecb0 100644 --- a/drivers/dahdi/wcte43x-base.c +++ b/drivers/dahdi/wcte43x-base.c @@ -91,8 +91,9 @@ struct t43x; struct t43x_span { struct t43x *owner; struct dahdi_span span; -#define NMF_FLAGBIT 1 -#define SENDINGYELLOW_FLAGBIT 2 +#define NMF_FLAGBIT 1 +#define SENDINGYELLOW_FLAGBIT 2 +#define HAVE_OPEN_CHANNELS_FLAGBIT 3 unsigned long bit_flags; unsigned char txsigs[16]; /* Copy of tx sig registers */ unsigned long lofalarmtimer; @@ -1719,10 +1720,21 @@ static void t43x_configure_e1(struct t43x *wc, int span_idx, int lineconfig) framing, line, crc4); } +static bool have_open_channels(const struct t43x_span *ts) +{ + int x, j; + for (x = 0, j = 0; x < ts->span.channels; x++) { + const struct dahdi_chan *chan = ts->span.chans[x]; + if (test_bit(DAHDI_FLAGBIT_OPEN, &chan->flags) || + dahdi_have_netdev(chan)) + return true; + } + return false; +} + static void t43x_framer_start(struct t43x *wc) { int unit; - struct t43x_span *ts; unsigned long flags; int res; @@ -1739,7 +1751,7 @@ static void t43x_framer_start(struct t43x *wc) dev_warn(&wc->xb.pdev->dev, "DMA engine did not stop.\n"); for (unit = 0; unit < wc->numspans; unit++) { - ts = wc->tspans[unit]; + struct t43x_span *ts = wc->tspans[unit]; if (dahdi_is_e1_span(&ts->span)) { t43x_configure_e1(wc, unit, ts->span.lineconfig); } else { /* is a T1 card */ @@ -1753,6 +1765,15 @@ static void t43x_framer_start(struct t43x *wc) for (unit = 0; unit < wc->numspans; unit++) { /* Get this party started */ + struct t43x_span *ts = wc->tspans[unit]; + + /* Check for "open channels" here in case some channels have + * netdev. */ + if (have_open_channels(ts)) + clear_bit(HAVE_OPEN_CHANNELS_FLAGBIT, &ts->bit_flags); + else + set_bit(HAVE_OPEN_CHANNELS_FLAGBIT, &ts->bit_flags); + local_irq_save(flags); t43x_check_alarms(wc, unit); t43x_check_sigbits(wc, unit); @@ -1774,7 +1795,7 @@ static void t43x_framer_start(struct t43x *wc) /* Clear all counters */ for (unit = 0; unit < wc->numspans; unit++) { - ts = wc->tspans[unit]; + struct t43x_span *ts = wc->tspans[unit]; memset(&ts->span.count, 0, sizeof(ts->span.count)); } @@ -2657,7 +2678,6 @@ static void t43x_check_alarms(struct t43x *wc, int span_idx) struct t43x_span *ts = wc->tspans[span_idx]; unsigned char c, d; int alarms; - int x, j; int fidx = (wc->numspans == 2) ? span_idx+1 : span_idx; if (!(test_bit(DAHDI_FLAGBIT_RUNNING, &ts->span.flags))) @@ -2699,11 +2719,7 @@ static void t43x_check_alarms(struct t43x *wc, int span_idx) } if (ts->span.lineconfig & DAHDI_CONFIG_NOTOPEN) { - for (x = 0, j = 0; x < ts->span.channels; x++) - if ((ts->chans[x]->flags & DAHDI_FLAG_OPEN) || - dahdi_have_netdev(ts->chans[x])) - j++; - if (!j) + if (!test_bit(HAVE_OPEN_CHANNELS_FLAGBIT, &ts->bit_flags)) alarms |= DAHDI_ALARM_NOTOPEN; else alarms &= ~DAHDI_ALARM_NOTOPEN; @@ -3157,6 +3173,45 @@ static void t43x_timer(unsigned long data) return; } +static int t43x_open(struct dahdi_chan *chan) +{ + struct t43x *wc = chan->pvt; + struct t43x_span *ts = container_of(chan->span, struct t43x_span, span); + unsigned long flags; + + if (!(ts->span.lineconfig & DAHDI_CONFIG_NOTOPEN)) + return 0; + + if (!test_and_set_bit(HAVE_OPEN_CHANNELS_FLAGBIT, &ts->bit_flags)) { + local_irq_save(flags); + t43x_check_alarms(wc, ts->span.offset); + local_irq_restore(flags); + } + + return 0; +} + +static int t43x_close(struct dahdi_chan *chan) +{ + struct t43x *wc = chan->pvt; + struct t43x_span *ts = container_of(chan->span, struct t43x_span, span); + unsigned long flags; + + if (!(ts->span.lineconfig & DAHDI_CONFIG_NOTOPEN)) + return 0; + + if (have_open_channels(ts)) + return 0; + + if (!test_and_set_bit(HAVE_OPEN_CHANNELS_FLAGBIT, &ts->bit_flags)) { + local_irq_save(flags); + t43x_check_alarms(wc, ts->span.offset); + local_irq_restore(flags); + } + + return 0; +} + static const struct dahdi_span_ops t43x_span_ops = { .owner = THIS_MODULE, .spanconfig = t43x_spanconfig, @@ -3169,6 +3224,8 @@ static const struct dahdi_span_ops t43x_span_ops = { .set_spantype = t43x_set_linemode, .echocan_create = t43x_echocan_create, .echocan_name = t43x_echocan_name, + .open = t43x_open, + .close = t43x_close, }; /**