wcte12xp, wctdm24xxp: Separate test for VPMADT032 and initialization.

Part of increasing system startup speed.

Splitting these two operations facilitate checking if there is a module
present synchronously on driver load from the actual load of the firmware and
configuration of the channels.

This will allow the presence of the VPM module to be flagged on the span
before registration, but load and configuration can happen in the background.
When the modules are eventually loaded via udev, there will be enough time
from the time the drivers are loaded to when dahdi_cfg will run to complete
the firmware load, eliminating the need to block the driver here.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9951 a0bf4364-ded3-4de4-8d8a-66a801d63aff
This commit is contained in:
Shaun Ruffell 2011-06-02 20:02:28 +00:00
parent 205847da8e
commit 77dfe92f26
4 changed files with 125 additions and 52 deletions

View File

@ -513,6 +513,11 @@ vpmadt032_alloc(struct vpmadt032_options *options)
sema_init(&vpm->sem, 1);
vpm->curpage = 0x80;
vpm->dspid = -1;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
INIT_WORK(&vpm->work, vpmadt032_bh, vpm);
#else
INIT_WORK(&vpm->work, vpmadt032_bh);
#endif
/* Do not use the global workqueue for processing these events. Some of
* the operations can take 100s of ms, most of that time spent sleeping.
@ -605,36 +610,26 @@ int vpmadt032_reset(struct vpmadt032 *vpm)
}
EXPORT_SYMBOL(vpmadt032_reset);
int
vpmadt032_init(struct vpmadt032 *vpm, struct voicebus *vb)
/**
* vpmadt032_test - Check if there is a VPMADT032 present on voicebus device.
* @vpm: Allocated with vpmadt032_alloc previously.
* @vb: Voicebus structure to test on.
*
* Returns 0 if there is a device, otherwise -ENODEV.
*
*/
int vpmadt032_test(struct vpmadt032 *vpm, struct voicebus *vb)
{
int i;
u16 reg;
int res = -EFAULT;
unsigned long stoptime;
struct device *dev;
gpakPingDspStat_t pingstatus;
BUG_ON(!vpm->setchanconfig_from_state);
BUG_ON(!vpm->wq);
BUG_ON(!vb);
u8 reg;
int i, x;
struct device *dev = &vb->pdev->dev;
vpm->vb = vb;
might_sleep();
dev = &vpm->vb->pdev->dev;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
INIT_WORK(&vpm->work, vpmadt032_bh, vpm);
#else
INIT_WORK(&vpm->work, vpmadt032_bh);
#endif
if (vpm->options.debug & DEBUG_VPMADT032_ECHOCAN)
dev_info(dev, "VPMADT032 Testing page access: ");
for (i = 0; i < 0xf; i++) {
int x;
for (x = 0; x < 3; x++) {
vpmadt032_setpage(vpm, i);
reg = vpmadt032_getpage(vpm);
@ -645,14 +640,42 @@ vpmadt032_init(struct vpmadt032 *vpm, struct voicebus *vb)
"VPMADT032 Failed HI page " \
"test\n", i, reg);
}
res = -ENODEV;
goto failed_exit;
return -ENODEV;
}
}
}
if (vpm->options.debug & DEBUG_VPMADT032_ECHOCAN)
dev_info(&vpm->vb->pdev->dev, "Passed\n");
dev_info(dev, "Passed\n");
return 0;
}
EXPORT_SYMBOL(vpmadt032_test);
/**
* vpmadt032_init - Initialize and load VPMADT032 firmware.
* @vpm: Allocated with vpmadt032_alloc previously.
*
* Returns 0 on success. This must be called after vpmadt032_test already
* checked if there appears to be a VPMADT032 installed on the board.
*
*/
int vpmadt032_init(struct vpmadt032 *vpm)
{
int i;
u16 reg;
int res = -EFAULT;
unsigned long stoptime;
struct device *dev;
gpakPingDspStat_t pingstatus;
BUG_ON(!vpm->setchanconfig_from_state);
BUG_ON(!vpm->wq);
BUG_ON(!vpm->vb);
might_sleep();
dev = &vpm->vb->pdev->dev;
stoptime = jiffies + 3*HZ;
set_bit(VPM150M_HPIRESET, &vpm->control);
@ -699,14 +722,14 @@ vpmadt032_init(struct vpmadt032 *vpm, struct voicebus *vb)
goto failed_exit;
}
res = vpmadtreg_loadfirmware(vb);
res = vpmadtreg_loadfirmware(vpm->vb);
if (res) {
dev_info(&vb->pdev->dev, "Failed to load the firmware.\n");
dev_info(&vpm->vb->pdev->dev, "Failed to load the firmware.\n");
return res;
}
vpm->curpage = -1;
dev_info(&vb->pdev->dev, "Booting VPMADT032\n");
dev_info(&vpm->vb->pdev->dev, "Booting VPMADT032\n");
stoptime = jiffies + 3*HZ;
set_bit(VPM150M_SWRESET, &vpm->control);
@ -723,7 +746,7 @@ vpmadt032_init(struct vpmadt032 *vpm, struct voicebus *vb)
pingstatus = gpakPingDsp(vpm->dspid, &vpm->version);
if (!pingstatus) {
dev_info(&vb->pdev->dev, "VPM present and operational "
dev_info(&vpm->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);

View File

@ -137,7 +137,8 @@ struct dahdi_echocanparam;
struct dahdi_echocan_state;
char vpmadt032tone_to_zaptone(GpakToneCodes_t tone);
int vpmadt032_init(struct vpmadt032 *vpm, struct voicebus *vb);
int vpmadt032_test(struct vpmadt032 *vpm, struct voicebus *vb);
int vpmadt032_init(struct vpmadt032 *vpm);
int vpmadt032_reset(struct vpmadt032 *vpm);
struct vpmadt032 *vpmadt032_alloc(struct vpmadt032_options *options);
void vpmadt032_free(struct vpmadt032 *vpm);

View File

@ -3841,7 +3841,9 @@ static int wctdm_initialize_vpmadt032(struct wctdm *wc)
/* wc->vpmadt032->context = wc; */
/* Pull the configuration information from the span holding
* the analog channels. */
res = vpmadt032_init(wc->vpmadt032, &wc->vb);
res = vpmadt032_test(wc->vpmadt032, &wc->vb);
if (!res)
res = vpmadt032_init(wc->vpmadt032);
if (res) {
vpmadt032_free(wc->vpmadt032);
wc->vpmadt032 = NULL;

View File

@ -1385,6 +1385,64 @@ struct vpm_load_work {
struct t1 *wc;
};
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
static void vpm_load_func(void *data)
{
struct maint_work_struct *w = data;
#else
static void vpm_load_func(struct work_struct *work)
{
struct vpm_load_work *w = container_of(work,
struct vpm_load_work, work);
#endif
struct t1 *wc = w->wc;
int res;
res = vpmadt032_init(wc->vpmadt032);
if (res) {
/* There was some problem during initialization, but it passed
* the address test, let's try again in a bit. */
wc->vpm_check = jiffies + HZ/2;
return;
}
if (config_vpmadt032(wc->vpmadt032, wc)) {
clear_bit(VPM150M_ACTIVE, &wc->ctlreg);
wc->vpm_check = jiffies + HZ/2;
return;
}
/* turn on vpm (RX audio from vpm module) */
set_bit(VPM150M_ACTIVE, &wc->ctlreg);
wc->vpm_check = jiffies + HZ*5;
if (vpmtsisupport) {
debug_printk(wc, 1, "enabling VPM TSI pin\n");
/* turn on vpm timeslot interchange pin */
set_bit(0, &wc->ctlreg);
}
set_bit(READY, &wc->bit_flags);
kfree(w);
}
static int vpm_start_load(struct t1 *wc)
{
struct vpm_load_work *work;
work = kzalloc(sizeof(*work), GFP_KERNEL);
if (!work)
return -ENOMEM;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
INIT_WORK(&work->work, vpm_load_func, work);
#else
INIT_WORK(&work->work, vpm_load_func);
#endif
work->wc = wc;
queue_work(wc->wq, &work->work);
return 0;
}
static int check_and_load_vpm(struct t1 *wc)
{
int res;
@ -1428,7 +1486,7 @@ static int check_and_load_vpm(struct t1 *wc)
wc->vpmadt032 = vpm;
spin_unlock_irqrestore(&wc->reglock, flags);
res = vpmadt032_init(vpm, &wc->vb);
res = vpmadt032_test(vpm, &wc->vb);
if (-ENODEV == res) {
struct vpmadt032 *vpm = wc->vpmadt032;
@ -1439,30 +1497,19 @@ static int check_and_load_vpm(struct t1 *wc)
spin_unlock_irqrestore(&wc->reglock, flags);
vpmadt032_free(vpm);
return res;
} else if (res) {
/* There was some problem during initialization, but it passed
* the address test, let's try again in a bit. */
wc->vpm_check = jiffies + HZ/2;
return -EAGAIN;
}
if (config_vpmadt032(vpm, wc)) {
res = vpm_start_load(wc);
if (res) {
/* There does not appear to be a VPMADT032 installed. */
clear_bit(VPM150M_ACTIVE, &wc->ctlreg);
wc->vpm_check = jiffies + HZ/2;
return -EAGAIN;
spin_lock_irqsave(&wc->reglock, flags);
wc->vpmadt032 = NULL;
spin_unlock_irqrestore(&wc->reglock, flags);
vpmadt032_free(vpm);
return res;
}
/* turn on vpm (RX audio from vpm module) */
set_bit(VPM150M_ACTIVE, &wc->ctlreg);
wc->vpm_check = jiffies + HZ*5;
if (vpmtsisupport) {
debug_printk(wc, 1, "enabling VPM TSI pin\n");
/* turn on vpm timeslot interchange pin */
set_bit(0, &wc->ctlreg);
}
return 0;
return res;
}
#else
static inline int check_and_load_vpm(const struct t1 *wc)