summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/dahdi/voicebus/GpakCust.c81
-rw-r--r--drivers/dahdi/voicebus/GpakCust.h3
-rw-r--r--drivers/dahdi/wctdm24xxp/base.c4
-rw-r--r--drivers/dahdi/wcte12xp/base.c89
4 files changed, 125 insertions, 52 deletions
diff --git a/drivers/dahdi/voicebus/GpakCust.c b/drivers/dahdi/voicebus/GpakCust.c
index 9a36a2f..ebd60da 100644
--- a/drivers/dahdi/voicebus/GpakCust.c
+++ b/drivers/dahdi/voicebus/GpakCust.c
@@ -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);
diff --git a/drivers/dahdi/voicebus/GpakCust.h b/drivers/dahdi/voicebus/GpakCust.h
index bd3308e..758bc28 100644
--- a/drivers/dahdi/voicebus/GpakCust.h
+++ b/drivers/dahdi/voicebus/GpakCust.h
@@ -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);
diff --git a/drivers/dahdi/wctdm24xxp/base.c b/drivers/dahdi/wctdm24xxp/base.c
index 03d56e2..7107808 100644
--- a/drivers/dahdi/wctdm24xxp/base.c
+++ b/drivers/dahdi/wctdm24xxp/base.c
@@ -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;
diff --git a/drivers/dahdi/wcte12xp/base.c b/drivers/dahdi/wcte12xp/base.c
index 8698461..6ffb8ba 100644
--- a/drivers/dahdi/wcte12xp/base.c
+++ b/drivers/dahdi/wcte12xp/base.c
@@ -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;
- }
-
- /* 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);
+ spin_lock_irqsave(&wc->reglock, flags);
+ wc->vpmadt032 = NULL;
+ spin_unlock_irqrestore(&wc->reglock, flags);
+ vpmadt032_free(vpm);
+ return res;
}
-
- return 0;
+ return res;
}
#else
static inline int check_and_load_vpm(const struct t1 *wc)