diff --git a/drivers/dahdi/wct4xxp/base.c b/drivers/dahdi/wct4xxp/base.c index 0f9e750..e7aa8bd 100644 --- a/drivers/dahdi/wct4xxp/base.c +++ b/drivers/dahdi/wct4xxp/base.c @@ -299,6 +299,7 @@ struct t4_span { unsigned long alarmcheck_time; int spanflags; int syncpos; + #ifdef SUPPORT_GEN1 int e1check; /* E1 check */ #endif @@ -345,6 +346,7 @@ struct t4 { int irq; /* IRQ used by device */ int order; /* Order */ const struct devtype *devtype; + unsigned int reset_required:1; /* If reset needed in serial_setup */ unsigned int falc31:1; /* are we falc v3.1 (atomic not necessary) */ unsigned int t1e1:8; /* T1 / E1 select pins */ int ledreg; /* LED Register */ @@ -1893,6 +1895,33 @@ static void setup_chunks(struct t4 *wc, int which) } } +static int __t4_hardware_init_1(struct t4 *wc, unsigned int cardflags, + bool first_time); +static int __t4_hardware_init_2(struct t4 *wc, bool first_time); + +static int t4_hardware_stop(struct t4 *wc); + +static void t4_framer_reset(struct t4 *wc) +{ + const bool first_time = false; + bool have_vpm = wc->vpm != NULL; + if (have_vpm) { + release_vpm450m(wc->vpm); + wc->vpm = NULL; + } + t4_hardware_stop(wc); + __t4_set_sclk_src(wc, WC_SELF, 0, 0); + __t4_hardware_init_1(wc, wc->devtype->flags, first_time); + __t4_hardware_init_2(wc, first_time); + if (have_vpm) { + t4_vpm_init(wc); + wc->dmactrl |= (wc->vpm) ? T4_VPM_PRESENT : 0; + t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); + } + setup_chunks(wc, 0); + wc->lastindex = 0; +} + /** * t4_serial_setup - Setup serial parameters and system interface. * @wc: The card to configure. @@ -1902,6 +1931,7 @@ static void t4_serial_setup(struct t4 *wc) { unsigned long flags; unsigned int unit; + bool reset_required = false; if (debug) { dev_info(&wc->dev->dev, @@ -1909,6 +1939,14 @@ static void t4_serial_setup(struct t4 *wc) wc->numspans); } + spin_lock_irqsave(&wc->reglock, flags); + reset_required = wc->reset_required > 0; + wc->reset_required = 0; + spin_unlock_irqrestore(&wc->reglock, flags); + + if (reset_required) + t4_framer_reset(wc); + spin_lock_irqsave(&wc->reglock, flags); /* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from * channel 0 */ @@ -2059,6 +2097,7 @@ static void t4_span_assigned(struct dahdi_span *span) struct t4 *wc = tspan->owner; struct dahdi_span *pos; unsigned int unassigned_spans = 0; + unsigned long flags; /* We use this to make sure all the spans are assigned before * running the serial setup. */ @@ -2067,8 +2106,14 @@ static void t4_span_assigned(struct dahdi_span *span) ++unassigned_spans; } - if (0 == unassigned_spans) + if (0 == unassigned_spans) { t4_serial_setup(wc); + + set_bit(T4_CHECK_TIMING, &wc->checkflag); + spin_lock_irqsave(&wc->reglock, flags); + __t4_set_sclk_src(wc, WC_SELF, 0, 0); + spin_unlock_irqrestore(&wc->reglock, flags); + } } static void free_wc(struct t4 *wc) @@ -2230,6 +2275,7 @@ static int t4_set_linemode(struct dahdi_span *span, enum spantypes linemode) enum linemode mode; const char *old_name; static DEFINE_MUTEX(linemode_lock); + unsigned long flags; dev_dbg(&wc->dev->dev, "Setting '%s' to '%s'\n", span->name, dahdi_spantype2str(linemode)); @@ -2237,6 +2283,10 @@ static int t4_set_linemode(struct dahdi_span *span, enum spantypes linemode) if (span->spantype == linemode) return 0; + spin_lock_irqsave(&wc->reglock, flags); + wc->reset_required = 1; + spin_unlock_irqrestore(&wc->reglock, flags); + /* Do not allow the t1e1 member to be changed by multiple threads. */ mutex_lock(&linemode_lock); old_name = dahdi_spantype2str(span->spantype); @@ -2833,6 +2883,10 @@ static void __t4_configure_e1(struct t4 *wc, int unit, int lineconfig) __t4_framer_out(wc, unit, 0x17, 0x04 | imr3extra); /* IMR3: AIS */ __t4_framer_out(wc, unit, 0x18, 0x3f); /* IMR4: We care about slips on transmit */ + __t4_framer_out(wc, unit, 0x2f, 0x00); + __t4_framer_out(wc, unit, 0x30, 0x00); + __t4_framer_out(wc, unit, 0x31, 0x00); + dev_info(&wc->dev->dev, "TE%dXXP: Span %d configured for %s/%s%s\n", wc->numspans, unit + 1, framing, line, crc4); } @@ -4868,17 +4922,18 @@ cleanup: return res; } -static int t4_hardware_init_1(struct t4 *wc, unsigned int cardflags) +static int +__t4_hardware_init_1(struct t4 *wc, unsigned int cardflags, bool first_time) { unsigned int version; int res; version = t4_pci_in(wc, WC_VERSION); - if (is_octal(wc)) { + if (is_octal(wc) && first_time) { dev_info(&wc->dev->dev, "Firmware Version: %01x.%02x\n", (version & 0xf00) >> 8, version & 0xff); - } else { + } else if (first_time) { dev_info(&wc->dev->dev, "Firmware Version: %08x\n", version); } if (debug) { @@ -4926,30 +4981,33 @@ static int t4_hardware_init_1(struct t4 *wc, unsigned int cardflags) t4_pci_out(wc, WC_INTR, 0x00000000); /* Read T1/E1 status */ - if (!strcasecmp("auto", default_linemode)) { - if (-1 == t1e1override) { - wc->t1e1 = (((t4_pci_in(wc, WC_LEDS)) & 0x0f00) >> 8); - wc->t1e1 &= 0xf; - if (is_octal(wc)) { - wc->t1e1 |= ((t4_pci_in(wc, WC_LEDS2)) & - 0x0f00) >> 4; + if (first_time) { + if (!strcasecmp("auto", default_linemode)) { + if (-1 == t1e1override) { + wc->t1e1 = (((t4_pci_in(wc, WC_LEDS)) & + 0x0f00) >> 8); + wc->t1e1 &= 0xf; + if (is_octal(wc)) { + wc->t1e1 |= ((t4_pci_in(wc, WC_LEDS2)) & + 0x0f00) >> 4; + } + } else { + dev_warn(&wc->dev->dev, + "'t1e1override' is deprecated. Please use 'default_linemode'.\n"); + wc->t1e1 = t1e1override & 0xf; } + } else if (!strcasecmp("t1", default_linemode)) { + wc->t1e1 = 0; + } else if (!strcasecmp("e1", default_linemode)) { + wc->t1e1 = 0xff; + } else if (!strcasecmp("j1", default_linemode)) { + wc->t1e1 = 0; + j1mode = 1; } else { - dev_warn(&wc->dev->dev, "'t1e1override' is deprecated. " - "Please use 'default_linemode'.\n"); - wc->t1e1 = t1e1override & 0xf; + dev_err(&wc->dev->dev, "'%s' is an unknown linemode.\n", + default_linemode); + wc->t1e1 = 0; } - } else if (!strcasecmp("t1", default_linemode)) { - wc->t1e1 = 0; - } else if (!strcasecmp("e1", default_linemode)) { - wc->t1e1 = 0xff; - } else if (!strcasecmp("j1", default_linemode)) { - wc->t1e1 = 0; - j1mode = 1; - } else { - dev_err(&wc->dev->dev, "'%s' is an unknown linemode.\n", - default_linemode); - wc->t1e1 = 0; } wc->order = ((t4_pci_in(wc, WC_LEDS)) & 0xf0000000) >> 28; @@ -4978,7 +5036,12 @@ static int t4_hardware_init_1(struct t4 *wc, unsigned int cardflags) return 0; } -static int t4_hardware_init_2(struct t4 *wc) +static int t4_hardware_init_1(struct t4 *wc, unsigned int cardflags) +{ + return __t4_hardware_init_1(wc, cardflags, true); +} + +static int __t4_hardware_init_2(struct t4 *wc, bool first_time) { int x; unsigned int regval; @@ -5010,13 +5073,14 @@ static int t4_hardware_init_2(struct t4 *wc) if (!is_octal(wc)) { regval = t4_framer_in(wc, 0, 0x4a); - if (regval == 0x05) { + if (first_time && regval == 0x05) { dev_info(&wc->dev->dev, "FALC Framer Version: 2.1 or " "earlier\n"); } else if (regval == 0x20) { - dev_info(&wc->dev->dev, "FALC Framer Version: 3.1\n"); + if (first_time) + dev_info(&wc->dev->dev, "FALC Framer Version: 3.1\n"); wc->falc31 = 1; - } else { + } else if (first_time) { dev_info(&wc->dev->dev, "FALC Framer Version: Unknown " "(VSTR = 0x%02x)\n", regval); } @@ -5036,14 +5100,24 @@ static int t4_hardware_init_2(struct t4 *wc) t4_pci_in(wc, x)); } } + + wc->gpio = 0x00000000; + t4_pci_out(wc, WC_GPIO, wc->gpio); + t4_gpio_setdir(wc, (1 << 17), (1 << 17)); + t4_gpio_setdir(wc, (0xff), (0xff)); + return 0; } +static int t4_hardware_init_2(struct t4 *wc) +{ + return __t4_hardware_init_2(wc, true); +} + static int __devinit t4_launch(struct t4 *wc) { int x; int res; - unsigned long flags; if (test_bit(DAHDI_FLAGBIT_REGISTERED, &wc->tspans[0]->span.flags)) return 0; @@ -5075,17 +5149,14 @@ static int __devinit t4_launch(struct t4 *wc) &wc->ddev->spans); } + tasklet_init(&wc->t4_tlet, t4_isr_bh, (unsigned long)wc); + res = dahdi_register_device(wc->ddev, &wc->dev->dev); if (res) { dev_err(&wc->dev->dev, "Failed to register with DAHDI.\n"); return res; } - set_bit(T4_CHECK_TIMING, &wc->checkflag); - spin_lock_irqsave(&wc->reglock, flags); - __t4_set_sclk_src(wc, WC_SELF, 0, 0); - spin_unlock_irqrestore(&wc->reglock, flags); - tasklet_init(&wc->t4_tlet, t4_isr_bh, (unsigned long)wc); return 0; } @@ -5299,10 +5370,6 @@ t4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev_info(&wc->dev->dev, "Found a Wildcard: %s\n", wc->devtype->desc); } - wc->gpio = 0x00000000; - t4_pci_out(wc, WC_GPIO, wc->gpio); - t4_gpio_setdir(wc, (1 << 17), (1 << 17)); - t4_gpio_setdir(wc, (0xff), (0xff)); #ifdef VPM_SUPPORT if (!wc->vpm) {