diff options
author | markster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2006-03-04 04:57:36 +0000 |
---|---|---|
committer | markster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2006-03-04 04:57:36 +0000 |
commit | 07bb7706f1f0156e13d6d0a64e86b4ba2b8b4791 (patch) | |
tree | 8490a6a31f2243ecf41d9d3659852c64a8a691c5 | |
parent | 67d950ad487f28bd4e5bb8f6fc6211f38399f1d8 (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
-rw-r--r-- | wct4xxp.c | 27 |
1 files changed, 17 insertions, 10 deletions
@@ -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); |