summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2011-01-21 05:29:25 +0000
committerShaun Ruffell <sruffell@digium.com>2011-01-21 05:29:25 +0000
commit135838c14b432cc801ff04c89dd51e72f88323d4 (patch)
tree8e241a88e3b5e047563a852e2069ee8f02176604
parente9f8bb7934d8ab5713ac23f7dd1a86841e90c90e (diff)
vpmadt032: Remove potential endless waits when resetting.
It is possible to softlock if the board stops delivering interrupts in the middle of a reset. Signed-off-by: Shaun Ruffell <sruffell@digium.com> Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=9332 git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.4@9668 a0bf4364-ded3-4de4-8d8a-66a801d63aff
-rw-r--r--drivers/dahdi/voicebus/GpakCust.c69
1 files changed, 60 insertions, 9 deletions
diff --git a/drivers/dahdi/voicebus/GpakCust.c b/drivers/dahdi/voicebus/GpakCust.c
index 7a2589a..d33779d 100644
--- a/drivers/dahdi/voicebus/GpakCust.c
+++ b/drivers/dahdi/voicebus/GpakCust.c
@@ -564,28 +564,46 @@ int vpmadt032_reset(struct vpmadt032 *vpm)
int res;
gpakPingDspStat_t pingstatus;
u16 version;
+ unsigned long stoptime;
+ struct device *const dev = &vpm->vb->pdev->dev;
might_sleep();
set_bit(VPM150M_HPIRESET, &vpm->control);
msleep(2000);
- while (test_bit(VPM150M_HPIRESET, &vpm->control))
+ /* It should never take longer than 5 seconds. */
+ stoptime = jiffies + 3*HZ;
+ while (test_bit(VPM150M_HPIRESET, &vpm->control) &&
+ time_before(jiffies, stoptime))
msleep(1);
+ if (time_after(jiffies, stoptime)) {
+ dev_dbg(dev, "Detected failure to clear HPIRESET.\n");
+ return -EIO;
+ }
+
/* 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");
+ dev_err(dev, "Failed to load VPMADT032 firmware.\n");
return res;
}
vpm->curpage = -1;
+ stoptime = jiffies + 3*HZ;
set_bit(VPM150M_SWRESET, &vpm->control);
- while (test_bit(VPM150M_SWRESET, &vpm->control))
+ while (test_bit(VPM150M_SWRESET, &vpm->control) &&
+ time_before(jiffies, stoptime))
msleep(1);
+ if (time_after(jiffies, stoptime)) {
+ dev_dbg(dev, "Detected failure to clear SWRESET.\n");
+ return -EIO;
+ }
+
+
/* Set us up to page 0 */
pingstatus = gpakPingDsp(vpm->dspid, &version);
if (!pingstatus) {
@@ -606,6 +624,8 @@ vpmadt032_init(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);
@@ -616,13 +636,15 @@ vpmadt032_init(struct vpmadt032 *vpm, struct voicebus *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(&vpm->vb->pdev->dev, "VPMADT032 Testing page access: ");
+ dev_info(dev, "VPMADT032 Testing page access: ");
for (i = 0; i < 0xf; i++) {
int x;
@@ -630,8 +652,12 @@ vpmadt032_init(struct vpmadt032 *vpm, struct voicebus *vb)
vpmadt032_setpage(vpm, i);
reg = vpmadt032_getpage(vpm);
if (reg != i) {
- if (vpm->options.debug & DEBUG_VPMADT032_ECHOCAN)
- dev_info(&vpm->vb->pdev->dev, "Failed: Sent %x != %x VPMADT032 Failed HI page test\n", i, reg);
+ if (vpm->options.debug &
+ DEBUG_VPMADT032_ECHOCAN) {
+ dev_err(dev, "Failed: Sent %x != %x " \
+ "VPMADT032 Failed HI page " \
+ "test\n", i, reg);
+ }
res = -ENODEV;
goto failed_exit;
}
@@ -641,9 +667,17 @@ vpmadt032_init(struct vpmadt032 *vpm, struct voicebus *vb)
if (vpm->options.debug & DEBUG_VPMADT032_ECHOCAN)
dev_info(&vpm->vb->pdev->dev, "Passed\n");
+ stoptime = jiffies + 3*HZ;
set_bit(VPM150M_HPIRESET, &vpm->control);
- while (test_bit(VPM150M_HPIRESET, &vpm->control))
+ while (test_bit(VPM150M_HPIRESET, &vpm->control) &&
+ time_before(jiffies, stoptime))
msleep(1);
+
+ if (time_after(jiffies, stoptime)) {
+ dev_dbg(dev, "Detected failure to clear HPIRESET.\n");
+ res = -EIO;
+ goto failed_exit;
+ }
msleep(250);
/* Set us up to page 0 */
@@ -666,10 +700,18 @@ vpmadt032_init(struct vpmadt032 *vpm, struct voicebus *vb)
if (vpm->options.debug & DEBUG_VPMADT032_ECHOCAN)
printk(KERN_CONT "Passed\n");
+ stoptime = jiffies + 3*HZ;
set_bit(VPM150M_HPIRESET, &vpm->control);
- while (test_bit(VPM150M_HPIRESET, &vpm->control))
+ while (test_bit(VPM150M_HPIRESET, &vpm->control) &&
+ time_before(jiffies, stoptime))
msleep(1);
+ if (time_after(jiffies, stoptime)) {
+ dev_dbg(dev, "Detected failure to clear SWRESET.\n");
+ res = -EIO;
+ goto failed_exit;
+ }
+
res = vpmadtreg_loadfirmware(vb);
if (res) {
dev_info(&vb->pdev->dev, "Failed to load the firmware.\n");
@@ -678,10 +720,19 @@ vpmadt032_init(struct vpmadt032 *vpm, struct voicebus *vb)
vpm->curpage = -1;
dev_info(&vb->pdev->dev, "Booting VPMADT032\n");
+
+ stoptime = jiffies + 3*HZ;
set_bit(VPM150M_SWRESET, &vpm->control);
- while (test_bit(VPM150M_SWRESET, &vpm->control))
+ while (test_bit(VPM150M_SWRESET, &vpm->control) &&
+ time_before(jiffies, stoptime))
msleep(1);
+ if (time_after(jiffies, stoptime)) {
+ dev_dbg(dev, "Detected failure to clear SWRESET.\n");
+ res = -EIO;
+ goto failed_exit;
+ }
+
pingstatus = gpakPingDsp(vpm->dspid, &vpm->version);
if (!pingstatus) {