diff options
-rw-r--r-- | drivers/dahdi/voicebus/GpakCust.c | 57 | ||||
-rw-r--r-- | drivers/dahdi/voicebus/GpakCust.h | 1 | ||||
-rw-r--r-- | drivers/dahdi/voicebus/voicebus.c | 2 | ||||
-rw-r--r-- | drivers/dahdi/wcte12xp/base.c | 333 | ||||
-rw-r--r-- | drivers/dahdi/wcte12xp/wcte12xp.h | 2 |
5 files changed, 262 insertions, 133 deletions
diff --git a/drivers/dahdi/voicebus/GpakCust.c b/drivers/dahdi/voicebus/GpakCust.c index 06e73be..991e02b 100644 --- a/drivers/dahdi/voicebus/GpakCust.c +++ b/drivers/dahdi/voicebus/GpakCust.c @@ -560,6 +560,47 @@ vpmadt032_alloc(struct vpmadt032_options *options, const char *board_name) } EXPORT_SYMBOL(vpmadt032_alloc); +int vpmadt032_reset(struct vpmadt032 *vpm) +{ + int res; + gpakPingDspStat_t pingstatus; + u16 version; + + might_sleep(); + + set_bit(VPM150M_HPIRESET, &vpm->control); + msleep(2000); + while (test_bit(VPM150M_HPIRESET, &vpm->control)) + msleep(1); + + /* Set us up to page 0 */ + vpmadt032_setpage(vpm, 0); + + res = vpmadtreg_loadfirmware(vpm->vb); + if (res) { + dev_info(&vpm->vb->pdev->dev, "Failed to load the firmware.\n"); + return res; + } + vpm->curpage = -1; + + set_bit(VPM150M_SWRESET, &vpm->control); + while (test_bit(VPM150M_SWRESET, &vpm->control)) + msleep(1); + + /* Set us up to page 0 */ + pingstatus = gpakPingDsp(vpm->dspid, &version); + if (!pingstatus) { + vpm_info(vpm, "VPM present and operational " + "(Firmware version %x)\n", version); + vpm->version = version; + res = 0; + } else { + res = -EIO; + } + return res; +} +EXPORT_SYMBOL(vpmadt032_reset); + int vpmadt032_init(struct vpmadt032 *vpm, struct voicebus *vb) { @@ -597,9 +638,9 @@ vpmadt032_init(struct vpmadt032 *vpm, struct voicebus *vb) dev_info(&vpm->vb->pdev->dev, "Passed\n"); set_bit(VPM150M_HPIRESET, &vpm->control); - msleep(2000); while (test_bit(VPM150M_HPIRESET, &vpm->control)) msleep(1); + msleep(250); /* Set us up to page 0 */ vpmadt032_setpage(vpm, 0); @@ -613,9 +654,8 @@ vpmadt032_init(struct vpmadt032 *vpm, struct voicebus *vb) vpmadt032_getreg(vpm, 0x1000, ®); if (reg != i) { printk(KERN_CONT "VPMADT032 Failed address test\n"); - goto failed_exit; + res = -EIO; } - } } @@ -641,11 +681,11 @@ vpmadt032_init(struct vpmadt032 *vpm, struct voicebus *vb) pingstatus = gpakPingDsp(vpm->dspid, &vpm->version); if (!pingstatus) { - dev_info(&vpm->vb->pdev->dev, - "Version of DSP is %x\n", vpm->version); + dev_info(&vb->pdev->dev, "VPM present and operational " + "(Firmware version %x)\n", vpm->version); } else { dev_notice(&vpm->vb->pdev->dev, "VPMADT032 Failed! Unable to ping the DSP (%d)!\n", pingstatus); - res = -1; + res = -EIO; goto failed_exit; } @@ -662,6 +702,7 @@ failed_exit: } EXPORT_SYMBOL(vpmadt032_init); + void vpmadt032_get_default_parameters(struct GpakEcanParms *p) { memset(p, 0, sizeof(*p)); @@ -694,7 +735,9 @@ void vpmadt032_free(struct vpmadt032 *vpm) struct change_order *order; LIST_HEAD(local_list); - BUG_ON(!vpm); + if (!vpm) + return; + BUG_ON(!vpm->wq); destroy_workqueue(vpm->wq); diff --git a/drivers/dahdi/voicebus/GpakCust.h b/drivers/dahdi/voicebus/GpakCust.h index 27499bd..915a642 100644 --- a/drivers/dahdi/voicebus/GpakCust.h +++ b/drivers/dahdi/voicebus/GpakCust.h @@ -136,6 +136,7 @@ struct dahdi_echocan_state; char vpmadt032tone_to_zaptone(GpakToneCodes_t tone); int vpmadt032_init(struct vpmadt032 *vpm, struct voicebus *vb); +int vpmadt032_reset(struct vpmadt032 *vpm); struct vpmadt032 *vpmadt032_alloc(struct vpmadt032_options *options, const char *board_name); void vpmadt032_free(struct vpmadt032 *vpm); diff --git a/drivers/dahdi/voicebus/voicebus.c b/drivers/dahdi/voicebus/voicebus.c index 9ae2155..a3fb42e 100644 --- a/drivers/dahdi/voicebus/voicebus.c +++ b/drivers/dahdi/voicebus/voicebus.c @@ -1757,7 +1757,7 @@ int vpmadtreg_loadfirmware(struct voicebus *vb) spin_unlock(&loader_list_lock); dev_info(&vb->pdev->dev, "Failed to find a registered " "loader after loading module.\n"); - ret = -1; + ret = -ENODEV; } return ret; } diff --git a/drivers/dahdi/wcte12xp/base.c b/drivers/dahdi/wcte12xp/base.c index 1ff0954..0ba87ba 100644 --- a/drivers/dahdi/wcte12xp/base.c +++ b/drivers/dahdi/wcte12xp/base.c @@ -963,26 +963,6 @@ static int t1xxp_chanconfig(struct dahdi_chan *chan, int sigtype) return 0; } -static int t1xxp_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc) -{ - struct t1 *wc = span->pvt; - - /* Do we want to SYNC on receive or not */ - if (lc->sync) { - set_bit(7, &wc->ctlreg); - span->syncsrc = span->spanno; - } else { - clear_bit(7, &wc->ctlreg); - span->syncsrc = 0; - } - - /* If already running, apply changes immediately */ - if (test_bit(DAHDI_FLAGBIT_RUNNING, &span->flags)) - return t1xxp_startup(span); - - return 0; -} - static int t1xxp_rbsbits(struct dahdi_chan *chan, int bits) { u_char m,c; @@ -1355,6 +1335,119 @@ static void set_span_devicetype(struct t1 *wc) #endif } +static void +setchanconfig_from_state(struct vpmadt032 *vpm, int channel, + GpakChannelConfig_t *chanconfig) +{ + const struct vpmadt032_options *options; + GpakEcanParms_t *p; + + BUG_ON(!vpm); + + options = &vpm->options; + + chanconfig->PcmInPortA = 3; + chanconfig->PcmInSlotA = (channel + 1) * 2; + chanconfig->PcmOutPortA = SerialPortNull; + chanconfig->PcmOutSlotA = (channel + 1) * 2; + chanconfig->PcmInPortB = 2; + chanconfig->PcmInSlotB = (channel + 1) * 2; + chanconfig->PcmOutPortB = 3; + chanconfig->PcmOutSlotB = (channel + 1) * 2; + chanconfig->ToneTypesA = Null_tone; + chanconfig->MuteToneA = Disabled; + chanconfig->FaxCngDetA = Disabled; + chanconfig->ToneTypesB = Null_tone; + chanconfig->EcanEnableA = Enabled; + chanconfig->EcanEnableB = Disabled; + chanconfig->MuteToneB = Disabled; + chanconfig->FaxCngDetB = Disabled; + + chanconfig->SoftwareCompand = cmpNone; + + chanconfig->FrameRate = rate10ms; + + p = &chanconfig->EcanParametersA; + + vpmadt032_get_default_parameters(p); + + p->EcanNlpType = vpm->curecstate[channel].nlp_type; + p->EcanNlpThreshold = vpm->curecstate[channel].nlp_threshold; + p->EcanNlpMaxSuppress = vpm->curecstate[channel].nlp_max_suppress; + + memcpy(&chanconfig->EcanParametersB, + &chanconfig->EcanParametersA, + sizeof(chanconfig->EcanParametersB)); +} + +static int +t1xxp_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc) +{ + struct vpmadt032_options options; + struct t1 *wc = span->pvt; + int res; + +#ifdef VPM_SUPPORT + if (!fatal_signal_pending(current) && vpmsupport) { + struct vpmadt032 *vpm; + memset(&options, 0, sizeof(options)); + options.debug = debug; + options.vpmnlptype = vpmnlptype; + options.vpmnlpthresh = vpmnlpthresh; + options.vpmnlpmaxsupp = vpmnlpmaxsupp; + options.channels = (wc->spantype == TYPE_T1) ? 24 : 32; + + wc->vpm_check = jiffies + HZ*600; + wc->vpmadt032 = vpmadt032_alloc(&options, wc->name); + if (!wc->vpmadt032) + return -ENOMEM; + + vpm = wc->vpmadt032; + vpm->setchanconfig_from_state = setchanconfig_from_state; + + res = vpmadt032_init(vpm, &wc->vb); + if (-ENODEV == res) { + wc->vpm_check = jiffies + HZ*600; + vpmadt032_free(vpm); + wc->vpmadt032 = NULL; + } else if (res) { + wc->vpm_check = jiffies + HZ/2; + } else { + config_vpmadt032(vpm, wc); + + set_span_devicetype(wc); + /* turn on vpm (RX audio from vpm module) */ + wc->ctlreg |= 0x10; + wc->vpm_check = HZ*5; + if (vpmtsisupport) { + debug_printk(wc, 1, "enabling VPM TSI pin\n"); + /* turn on vpm timeslot interchange pin */ + wc->ctlreg |= 0x01; + } + } + } else { + t1_info(wc, "VPM Support Disabled\n"); + wc->vpmadt032 = NULL; + } +#endif + + /* Do we want to SYNC on receive or not */ + if (lc->sync) { + set_bit(7, &wc->ctlreg); + span->syncsrc = span->spanno; + } else { + clear_bit(7, &wc->ctlreg); + span->syncsrc = 0; + } + + /* If already running, apply changes immediately */ + if (test_bit(DAHDI_FLAGBIT_RUNNING, &span->flags)) + return t1xxp_startup(span); + + return 0; +} + + static int t1_software_init(struct t1 *wc) { int x; @@ -1453,54 +1546,9 @@ static inline unsigned char t1_vpm_out(struct t1 *wc, int unit, const unsigned i #endif #endif -static void setchanconfig_from_state(struct vpmadt032 *vpm, int channel, GpakChannelConfig_t *chanconfig) -{ - const struct vpmadt032_options *options; - GpakEcanParms_t *p; - - BUG_ON(!vpm); - - options = &vpm->options; - - chanconfig->PcmInPortA = 3; - chanconfig->PcmInSlotA = (channel + 1) * 2; - chanconfig->PcmOutPortA = SerialPortNull; - chanconfig->PcmOutSlotA = (channel + 1) * 2; - chanconfig->PcmInPortB = 2; - chanconfig->PcmInSlotB = (channel + 1) * 2; - chanconfig->PcmOutPortB = 3; - chanconfig->PcmOutSlotB = (channel + 1) * 2; - chanconfig->ToneTypesA = Null_tone; - chanconfig->MuteToneA = Disabled; - chanconfig->FaxCngDetA = Disabled; - chanconfig->ToneTypesB = Null_tone; - chanconfig->EcanEnableA = Enabled; - chanconfig->EcanEnableB = Disabled; - chanconfig->MuteToneB = Disabled; - chanconfig->FaxCngDetB = Disabled; - - chanconfig->SoftwareCompand = cmpNone; - - chanconfig->FrameRate = rate10ms; - - p = &chanconfig->EcanParametersA; - - vpmadt032_get_default_parameters(p); - - p->EcanNlpType = vpm->curecstate[channel].nlp_type; - p->EcanNlpThreshold = vpm->curecstate[channel].nlp_threshold; - p->EcanNlpMaxSuppress = vpm->curecstate[channel].nlp_max_suppress; - - memcpy(&chanconfig->EcanParametersB, - &chanconfig->EcanParametersA, - sizeof(chanconfig->EcanParametersB)); -} - static int t1_hardware_post_init(struct t1 *wc) { - struct vpmadt032_options options; unsigned int reg; - int res; int x; /* T1 or E1 */ @@ -1532,43 +1580,6 @@ static int t1_hardware_post_init(struct t1 *wc) t1_setleds(wc, wc->ledstate); -#ifdef VPM_SUPPORT - if (!fatal_signal_pending(current) && vpmsupport) { - memset(&options, 0, sizeof(options)); - options.debug = debug; - options.vpmnlptype = vpmnlptype; - options.vpmnlpthresh = vpmnlpthresh; - options.vpmnlpmaxsupp = vpmnlpmaxsupp; - options.channels = (wc->spantype == TYPE_T1) ? 24 : 32; - - wc->vpmadt032 = vpmadt032_alloc(&options, wc->name); - if (!wc->vpmadt032) - return -ENOMEM; - - wc->vpmadt032->setchanconfig_from_state = setchanconfig_from_state; - - res = vpmadt032_init(wc->vpmadt032, &wc->vb); - if (res) { - vpmadt032_free(wc->vpmadt032); - wc->vpmadt032=NULL; - return -EIO; - } - - config_vpmadt032(wc->vpmadt032, wc); - - set_span_devicetype(wc); - t1_info(wc, "VPM present and operational " - "(Firmware version %x)\n", wc->vpmadt032->version); - wc->ctlreg |= 0x10; /* turn on vpm (RX audio from vpm module) */ - if (vpmtsisupport) { - debug_printk(wc, 1, "enabling VPM TSI pin\n"); - wc->ctlreg |= 0x01; /* turn on vpm timeslot interchange pin */ - } - } else { - t1_info(wc, "VPM Support Disabled\n"); - wc->vpmadt032 = NULL; - } -#endif return 0; } @@ -1802,15 +1813,12 @@ static inline void t1_transmitprep(struct t1 *wc, u8 *writechunk) } /* process the command queue */ - for (y = 0; y < 7; y++) { + for (y = 0; y < 7; y++) cmd_dequeue(wc, writechunk, x, y); - } + #ifdef VPM_SUPPORT - if(likely(wc->vpmadt032)) { - spin_lock(&wc->reglock); + if (wc->vpmadt032) cmd_dequeue_vpmadt032(wc, writechunk, x); - spin_unlock(&wc->reglock); - } #endif if (x < DAHDI_CHUNKSIZE - 1) { @@ -1912,26 +1920,97 @@ static void timer_work_func(struct work_struct *work) { struct t1 *wc = container_of(work, struct t1, timer_work); #endif - /* Called once every 100 ms */ - if (unlikely(!test_bit(INITIALIZED, &wc->bit_flags))) - return; t1_do_counters(wc); t1_check_alarms(wc); t1_check_sigbits(wc); mod_timer(&wc->timer, jiffies + HZ/10); } -static void -te12xp_timer(unsigned long data) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) +static void vpm_check_func(void *data) +{ + struct t1 *wc = data; +#else +static void vpm_check_func(struct work_struct *work) +{ + struct t1 *wc = container_of(work, struct t1, vpm_check_work); +#endif + int res; + u16 version; + unsigned long flags; + + res = gpakPingDsp(wc->vpmadt032->dspid, &version); + if (!res) { + spin_lock_irqsave(&wc->reglock, flags); + wc->ctlreg |= 0x10; + spin_unlock_irqrestore(&wc->reglock, flags); + return; + } + + /* Bypass the rx audio from the VPM module. */ + spin_lock_irqsave(&wc->reglock, flags); + wc->ctlreg &= ~(0x10); + spin_unlock_irqrestore(&wc->reglock, flags); + + t1_info(wc, "VPMADT032 is non-responsive. Resetting.\n"); + + res = vpmadt032_reset(wc->vpmadt032); + if (!res) { + config_vpmadt032(wc->vpmadt032, wc); + /* Looks like the reset went ok so we can put the VPM module + * back in the TDM path. */ + spin_lock_irqsave(&wc->reglock, flags); + wc->ctlreg |= 0x10; + spin_unlock_irqrestore(&wc->reglock, flags); + t1_info(wc, "VPMADT032 is reenabled.\n"); + } else { + t1_info(wc, "Failed VPMADT032 reset. " + "VPMADT032 is disabled.\n"); + } + + return; +} + +static void te12xp_timer(unsigned long data) { struct t1 *wc = (struct t1 *)data; + + if (unlikely(!test_bit(INITIALIZED, &wc->bit_flags))) + return; + queue_work(wc->wq, &wc->timer_work); + + if (!wc->vpmadt032) + return; + + if (time_after(wc->vpm_check, jiffies)) + return; + + /* We'll check the VPM module again in 5 seconds. */ + wc->vpm_check = jiffies + 5*HZ; + queue_work(wc->vpmadt032->wq, &wc->vpm_check_work); return; } +static void t1_handle_error(struct voicebus *vb) +{ + struct t1 *wc = container_of(vb, struct t1, vb); + unsigned long flags; + + if (wc->vpmadt032) { + /* Bypass the rx audio from the VPM module. */ + spin_lock_irqsave(&wc->reglock, flags); + wc->ctlreg &= ~(0x10); + spin_unlock_irqrestore(&wc->reglock, flags); + + queue_work(wc->vpmadt032->wq, &wc->vpm_check_work); + } +} + static const struct voicebus_operations voicebus_operations = { .handle_receive = t1_handle_receive, .handle_transmit = t1_handle_transmit, + .handle_error = t1_handle_error, }; static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -1984,6 +2063,12 @@ static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_devi INIT_WORK(&wc->timer_work, timer_work_func); # endif +# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + INIT_WORK(&wc->vpm_check_work, vpm_check_func, wc); +# else + INIT_WORK(&wc->vpm_check_work, vpm_check_func); +# endif + snprintf(wc->name, sizeof(wc->name)-1, "wcte12xp%d", index); pci_set_drvdata(pdev, wc); wc->vb.ops = &voicebus_operations; @@ -2041,33 +2126,31 @@ static void __devexit te12xp_remove_one(struct pci_dev *pdev) { struct t1 *wc = pci_get_drvdata(pdev); #ifdef VPM_SUPPORT - unsigned long flags; struct vpmadt032 *vpm = wc->vpmadt032; #endif if (!wc) return; -#ifdef VPM_SUPPORT - if(vpm) { - wc->vpmadt032 = NULL; - clear_bit(VPM150M_DTMFDETECT, &vpm->control); - clear_bit(VPM150M_ACTIVE, &vpm->control); - } -#endif clear_bit(INITIALIZED, &wc->bit_flags); + del_timer_sync(&wc->timer); flush_workqueue(wc->wq); +#ifdef VPM_SUPPORT + if (vpm) + flush_workqueue(vpm->wq); +#endif del_timer_sync(&wc->timer); - voicebus_release(&wc->vb); - #ifdef VPM_SUPPORT if(vpm) { - spin_lock_irqsave(&wc->reglock, flags); - spin_unlock_irqrestore(&wc->reglock, flags); + wc->vpmadt032 = NULL; + clear_bit(VPM150M_DTMFDETECT, &vpm->control); + clear_bit(VPM150M_ACTIVE, &vpm->control); vpmadt032_free(vpm); } #endif + + voicebus_release(&wc->vb); t1_release(wc); } diff --git a/drivers/dahdi/wcte12xp/wcte12xp.h b/drivers/dahdi/wcte12xp/wcte12xp.h index f7cae2f..1505fcc 100644 --- a/drivers/dahdi/wcte12xp/wcte12xp.h +++ b/drivers/dahdi/wcte12xp/wcte12xp.h @@ -126,6 +126,8 @@ struct t1 { atomic_t txints; int vpm100; struct vpmadt032 *vpmadt032; + unsigned long vpm_check; + struct work_struct vpm_check_work; unsigned long dtmfactive; unsigned long dtmfmask; unsigned long dtmfmutemask; |