ovpxa24xx: Try to resume the device with minimal state changes after bad DMA (EEH)

parent 69f30967
......@@ -947,6 +947,9 @@ static void a24xx_proslic_check_hook(struct a24xx *wc, int card)
int hook;
struct a24xx_dev *wc_dev = &wc->dev;
if (wc_dev->eeh_triggered)
return;
/* For some reason we have to debounce the
hook detector. */
......@@ -1096,6 +1099,9 @@ DAHDI_IRQ_HANDLER(a24xx_interrupt)
if (!ints)
return IRQ_NONE;
if (wc_dev->eeh_triggered)
return IRQ_RETVAL(1);
__opvx_a24xx_set_irqstatus(wc_dev, ints); // clear interrupt register.
for (x=0;x<wc_dev->max_cards; x++) {
......@@ -1143,6 +1149,9 @@ DAHDI_IRQ_HANDLER(a24xx_interrupt)
}
}
if (wc_dev->eeh_triggered)
return IRQ_RETVAL(1);
if (ints & (1<<16)) { /* it is our interrupts */
wc_dev->intcount++;
switch(ms_per_irq){
......@@ -1331,7 +1340,10 @@ DAHDI_IRQ_HANDLER(a24xx_interrupt)
}
break;
}
if (wc_dev->eeh_triggered)
return IRQ_RETVAL(1);
if (!(wc_dev->intcount % ( 10000/ms_per_irq ))) {
/* Accept an alarm once per 10 seconds */
for (x=0;x<wc_dev->max_cards;x++)
......@@ -1341,6 +1353,11 @@ DAHDI_IRQ_HANDLER(a24xx_interrupt)
}
}
}
if (wc_dev->eeh_triggered)
return IRQ_RETVAL(1);
/**/
for(order=0;order < ms_per_irq;order++){
a24xx_receive(wc, order);
......@@ -1371,6 +1388,9 @@ static int interrupt_onecard_handler(struct a24xx *wc)
return IRQ_NONE;
}
if (wc_dev->eeh_triggered)
return 0;
__opvx_a24xx_set_irqstatus(wc_dev, ints); // clear interrupt register.
for (x=0;x<wc_dev->max_cards; x++) {
......@@ -1417,6 +1437,9 @@ static int interrupt_onecard_handler(struct a24xx *wc)
}
}
if (wc_dev->eeh_triggered)
return 0;
if ( ((ints & (1<<16)) && wc_dev->master) || (!wc_dev->master)) { /* it is our interrupts */
wc_dev->intcount++;
switch(ms_per_irq){
......@@ -1605,7 +1628,11 @@ static int interrupt_onecard_handler(struct a24xx *wc)
}
break;
}
if (wc_dev->eeh_triggered)
return 0;
if (!(wc_dev->intcount % ( 10000/ms_per_irq ))) {
/* Accept an alarm once per 10 seconds */
for (x=0;x<wc_dev->max_cards;x++)
......@@ -1615,6 +1642,10 @@ static int interrupt_onecard_handler(struct a24xx *wc)
}
}
}
if (wc_dev->eeh_triggered)
return 0;
/**/
for(order=0;order < ms_per_irq;order++){
dahdi_transmit(&wc->span);
......@@ -1747,6 +1778,10 @@ static int a24xx_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long
struct fxs *const fxs = &wc_dev->mod[chan->chanpos - 1].fxs;
if (wc_dev->eeh_triggered)
return -EFAULT;
switch (cmd) {
case DAHDI_ONHOOKTRANSFER:
if (wc_dev->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) {
......@@ -2288,6 +2323,7 @@ static int __devinit a24xx_init_one(struct pci_dev *pdev, const struct pci_devic
wc_dev = &wc->dev;
wc_dev->ledstate = 0;
wc_dev->device_id = *ent;
wc_dev->eeh_triggered = 0;
for (x=0; x < sizeof(wc->chans)/sizeof(wc->chans[0]); ++x) {
wc->chans[x] = &wc->_chans[x];
......@@ -2718,18 +2754,12 @@ static void __exit a24xx_cleanup(void)
* Return value:
* PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT
*/
static pci_ers_result_t a24xx_pci_error_detected(struct pci_dev *pdev,
static pci_ers_result_t a24xx_pci_error_detected(struct pci_dev __maybe_unused *pdev,
pci_channel_state_t state)
{
struct a24xx *wc = pci_get_drvdata(pdev);
struct a24xx_dev *wc_dev = &wc->dev;
if (state == pci_channel_io_perm_failure)
return PCI_ERS_RESULT_DISCONNECT;
__opvx_a24xx_disable_interrupts(wc_dev);
__opvx_a24xx_stop_dma(wc_dev);
printk(KERN_WARNING "OpenVox: Non-correctable non-fatal error reported, unfreezing...\n");
return PCI_ERS_RESULT_CAN_RECOVER;
}
......@@ -2751,19 +2781,17 @@ static pci_ers_result_t a24xx_pci_mmio_enabled(struct pci_dev __maybe_unused *pd
*
*/
static void a24xx_pci_resume(struct pci_dev *pdev)
static void a24xx_pci_resume(struct pci_dev __maybe_unused *pdev)
{
struct a24xx *wc = pci_get_drvdata(pdev);
struct a24xx_dev *wc_dev = &wc->dev;
printk(KERN_WARNING "OpenVox: Resuming operations after thaw...\n");
__opvx_a24xx_enable_interrupts(wc_dev);
/* Initialize Write/Buffers to all blank data */
memset((void *)wc_dev->writechunk,0, ms_per_irq * DAHDI_MAX_CHUNKSIZE * MAX_NUM_CARDS * 2 * 2);
wc_dev->eeh_triggered = 0;
__opvx_a24xx_start_dma(wc_dev, wc_dev->writedma);
/* Try to pick up where the driver left off */
interrupt_onecard_handler(wc);
}
/**
......
......@@ -127,6 +127,7 @@ enum battery_state {
struct a24xx_dev {
struct pci_dev *dev;
struct pci_device_id device_id;
int eeh_triggered;
char *variety;
struct dahdi_device *ddev;
unsigned char ios;
......
......@@ -131,6 +131,7 @@ unsigned int __opvx_a24xx_getcreg(struct a24xx_dev *wc, unsigned int offset, uns
if (unlikely((*p) == ~((unsigned int)0))) {
struct eeh_dev *eehdev = pci_dev_to_eeh_dev(wc->dev);
eeh_dev_check_failure(eehdev);
wc->eeh_triggered = 1;
}
#endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment