summaryrefslogtreecommitdiff
path: root/wct4xxp.c
diff options
context:
space:
mode:
authormarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2006-03-04 04:57:36 +0000
committermarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2006-03-04 04:57:36 +0000
commit07bb7706f1f0156e13d6d0a64e86b4ba2b8b4791 (patch)
tree8490a6a31f2243ecf41d9d3659852c64a8a691c5 /wct4xxp.c
parent67d950ad487f28bd4e5bb8f6fc6211f38399f1d8 (diff)
Fix NMI issues with some IBM xSeries servers
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@975 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'wct4xxp.c')
-rw-r--r--wct4xxp.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/wct4xxp.c b/wct4xxp.c
index 0b3cb52..fd2b05e 100644
--- a/wct4xxp.c
+++ b/wct4xxp.c
@@ -299,6 +299,7 @@ struct t4 {
int flags; /* Device flags */
int master; /* Are we master */
int ledreg; /* LED Register */
+ int stopdma; /* Set to stop DMA */
unsigned int dmactrl;
int e1recover; /* E1 recovery timer */
dma_addr_t readdma;
@@ -398,7 +399,10 @@ static inline void __t4_pci_out(struct t4 *wc, const unsigned int addr, const un
{
unsigned int tmp;
wc->membase[addr] = cpu_to_le32(value);
-#if 1
+ tmp = __t4_pci_in(wc, WC_VERSION);
+ if ((tmp & 0xffff0000) != 0xc01a0000)
+ printk("TE4XXP: Version Synchronization Error!\n");
+#if 0
tmp = __t4_pci_in(wc, addr);
if ((value != tmp) && (addr != WC_LEDS) && (addr != WC_LDATA) &&
(addr != WC_GPIO) && (addr != WC_INTR))
@@ -446,6 +450,7 @@ static inline unsigned int __t4_framer_in(struct t4 *wc, int unit, const unsigne
unit &= 0x3;
__t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff));
__t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff) | WC_LFRMR_CS | WC_LREAD);
+ __t4_pci_out(wc, WC_VERSION, 0);
ret = __t4_pci_in(wc, WC_LDATA);
__t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff));
return ret & 0xff;
@@ -1145,11 +1150,7 @@ static int t4_shutdown(struct zt_span *span)
(!(wc->tspans[1]->span.flags & ZT_FLAG_RUNNING)))) {
/* No longer in use, disable interrupts */
printk("TE%dXXP: Disabling interrupts since there are no active spans\n", wc->numspans);
- wc->dmactrl = 0x0;
- __t4_pci_out(wc, WC_DMACTRL, 0x00000000);
- /* Acknowledge any pending interrupts */
- __t4_pci_out(wc, WC_INTR, 0x00000000);
- __t4_set_timing_source(wc, 4, 0, 0);
+ wc->stopdma = 1;
} else wc->checktiming = 1;
spin_unlock_irqrestore(&wc->reglock, flags);
if (debug & DEBUG_MAIN)
@@ -2725,6 +2726,15 @@ static void t4_interrupt_gen2(int irq, void *dev_id, struct pt_regs *regs)
if (wc->checktiming > 0)
__t4_set_timing_source_auto(wc);
+ if (wc->stopdma) {
+ /* Stop DMA cleanly if requested */
+ wc->dmactrl = 0x0;
+ __t4_pci_out(wc, WC_DMACTRL, 0x00000000);
+ /* Acknowledge any pending interrupts */
+ __t4_pci_out(wc, WC_INTR, 0x00000000);
+ __t4_set_timing_source(wc, 4, 0, 0);
+ wc->stopdma = 0x0;
+ }
spin_unlock_irqrestore(&wc->reglock, flags);
#ifndef ENABLE_WORKQUEUES
@@ -3299,10 +3309,7 @@ static int t4_hardware_stop(struct t4 *wc)
{
/* Turn off DMA, leave interrupts enabled */
- wc->dmactrl = 0x0000000;
- t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); /* Turn on only the read interrupts, not the write */
- t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
- t4_pci_out(wc, WC_INTR, 0x00000000);
+ wc->stopdma = 1;
current->state = TASK_UNINTERRUPTIBLE;
schedule_timeout((25 * HZ) / 1000);