Matthew,
I hope this looks like a good patch. Please review, apply and
forward upstream.
--linas
Various PCI bus errors can be signaled by newer PCI controllers.
This patch adds the PCI error recovery callbacks to the Symbios
SCSI device driver. The patch has been tested, and appears to
work well.
Signed-off-by: Linas Vepstas <redacted>
----
drivers/scsi/sym53c8xx_2/sym_glue.c | 97 ++++++++++++++++++++++++++++++++++++
drivers/scsi/sym53c8xx_2/sym_glue.h | 4 +
drivers/scsi/sym53c8xx_2/sym_hipd.c | 10 +++
3 files changed, 111 insertions(+)
Index: linux-2.6.18-rc7-git1/drivers/scsi/sym53c8xx_2/sym_glue.c
===================================================================
@@ -659,6 +659,11 @@ static irqreturn_t sym53c8xx_intr(int irif(DEBUG_FLAGS&DEBUG_TINY)printf_debug("[");+/* Avoid spinloop trying to handle interrupts on frozen device */+if((np->s.device->error_state!=pci_channel_io_normal)&&+(np->s.device->error_state!=0))+returnIRQ_HANDLED;+spin_lock_irqsave(np->s.host->host_lock,flags);sym_interrupt(np);spin_unlock_irqrestore(np->s.host->host_lock,flags);
@@ -726,6 +731,19 @@ static int sym_eh_handler(int op, char *dev_warn(&cmd->device->sdev_gendev,"%s operation started.\n",opname);+/* We may be in an error condition because the PCI bus+*wentdown.Inthiscase,weneedtowaituntilthe+*PCIbusisreset,thecardisreset,andonlythen+*proceedwiththescsierrorrecovery.There'sno+*pointinhurrying;takealeisurelywait.+*/+#define WAIT_FOR_PCI_RECOVERY 35+if((np->s.device->error_state!=pci_channel_io_normal)&&+(np->s.device->error_state!=0)&&+(0==wait_for_completion_timeout(&np->s.io_reset_wait,+WAIT_FOR_PCI_RECOVERY*HZ)))+returnSCSI_FAILED;+spin_lock_irq(host->host_lock);/* This one is queued in some place -> to wait for completion */FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq,qp){
@@ -1948,6 +1967,77 @@ static void __devexit sym2_remove(structattach_count--;}+/**+*sym2_io_error_detected()--calledwhenPCIerrorisdetected+*@pdev:pointertoPCIdevice+*@state:currentstateofthePCIslot+*/+staticpci_ers_result_tsym2_io_error_detected(structpci_dev*pdev,+enumpci_channel_statestate)+{+structsym_hcb*np=pci_get_drvdata(pdev);++/* If slot is permanently frozen, turn everything off */+if(state==pci_channel_io_perm_failure){+sym2_remove(pdev);+returnPCI_ERS_RESULT_DISCONNECT;+}++init_completion(&np->s.io_reset_wait);+disable_irq(pdev->irq);+pci_disable_device(pdev);++/* Request a slot slot reset. */+returnPCI_ERS_RESULT_NEED_RESET;+}++/**+*sym2_io_slot_reset()--calledwhenthepcibushasbeenreset.+*@pdev:pointertoPCIdevice+*+*Restartthecardfromscratch.+*/+staticpci_ers_result_tsym2_io_slot_reset(structpci_dev*pdev)+{+structsym_hcb*np=pci_get_drvdata(pdev);++printk(KERN_INFO"%s: recovering from a PCI slot reset\n",+sym_name(np));++if(pci_enable_device(pdev))+printk(KERN_ERR"%s: device setup failed most egregiously\n",+sym_name(np));++pci_set_master(pdev);+enable_irq(pdev->irq);++/* Perform host reset only on one instance of the card */+if(0==PCI_FUNC(pdev->devfn)){+if(sym_reset_scsi_bus(np,0)){+printk(KERN_ERR"%s: Unable to reset scsi host controller\n",+sym_name(np));+returnPCI_ERS_RESULT_DISCONNECT;+}+sym_start_up(np,1);+}++returnPCI_ERS_RESULT_RECOVERED;+}++/**+*sym2_io_resume()--resumenormalopsafterPCIreset+*@pdev:pointertoPCIdevice+*+*Calledwhentheerrorrecoverydrivertellsusthatits+*OKtoresumenormaloperation.Usecompletiontoallow+*haltedscsiopstoresume.+*/+staticvoidsym2_io_resume(structpci_dev*pdev)+{+structsym_hcb*np=pci_get_drvdata(pdev);+complete_all(&np->s.io_reset_wait);+}+staticvoidsym2_get_signalling(structScsi_Host*shost){structsym_hcb*np=sym_get_hcb(shost);
@@ -2809,6 +2811,14 @@ void sym_interrupt (struct sym_hcb *np)dstat|=INB(np,nc_dstat);istatc=INB(np,nc_istat);istat|=istatc;++/* Prevent deadlock waiting on a condition that may never clear. */+icnt++;+if(100<icnt){+if((np->s.device->error_state!=pci_channel_io_normal)+&&(np->s.device->error_state!=0))+return;+}}while(istatc&(SIP|DIP));if(DEBUG_FLAGS&DEBUG_TINY)
Luca
--
"L'abilita` politica e` l'abilita` di prevedere quello che
accadra` domani, la prossima settimana, il prossimo mese e
l'anno prossimo. E di essere cosi` abili, piu` tardi,
da spiegare perche' non e` accaduto."
Matthew,
Revised patch per comments from Luca,
Please review, apply and forward upstream.
--linas
Various PCI bus errors can be signaled by newer PCI controllers.
This patch adds the PCI error recovery callbacks to the Symbios
SCSI device driver. The patch has been tested, and appears to
work well.
Signed-off-by: Linas Vepstas <redacted>
--
drivers/scsi/sym53c8xx_2/sym_glue.c | 99 ++++++++++++++++++++++++++++++++++++
drivers/scsi/sym53c8xx_2/sym_glue.h | 4 +
drivers/scsi/sym53c8xx_2/sym_hipd.c | 10 +++
3 files changed, 113 insertions(+)
Index: linux-2.6.18-rc7-git1/drivers/scsi/sym53c8xx_2/sym_glue.c
===================================================================
@@ -659,6 +659,11 @@ static irqreturn_t sym53c8xx_intr(int irif(DEBUG_FLAGS&DEBUG_TINY)printf_debug("[");+/* Avoid spinloop trying to handle interrupts on frozen device */+if((np->s.device->error_state!=pci_channel_io_normal)&&+(np->s.device->error_state!=0))+returnIRQ_HANDLED;+spin_lock_irqsave(np->s.host->host_lock,flags);sym_interrupt(np);spin_unlock_irqrestore(np->s.host->host_lock,flags);
@@ -726,6 +731,19 @@ static int sym_eh_handler(int op, char *dev_warn(&cmd->device->sdev_gendev,"%s operation started.\n",opname);+/* We may be in an error condition because the PCI bus+*wentdown.Inthiscase,weneedtowaituntilthe+*PCIbusisreset,thecardisreset,andonlythen+*proceedwiththescsierrorrecovery.There'sno+*pointinhurrying;takealeisurelywait.+*/+#define WAIT_FOR_PCI_RECOVERY 35+if((np->s.device->error_state!=pci_channel_io_normal)&&+(np->s.device->error_state!=0)&&+(0==wait_for_completion_timeout(&np->s.io_reset_wait,+WAIT_FOR_PCI_RECOVERY*HZ)))+returnSCSI_FAILED;+spin_lock_irq(host->host_lock);/* This one is queued in some place -> to wait for completion */FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq,qp){
@@ -1948,6 +1967,79 @@ static void __devexit sym2_remove(structattach_count--;}+/**+*sym2_io_error_detected()--calledwhenPCIerrorisdetected+*@pdev:pointertoPCIdevice+*@state:currentstateofthePCIslot+*/+staticpci_ers_result_tsym2_io_error_detected(structpci_dev*pdev,+enumpci_channel_statestate)+{+structsym_hcb*np=pci_get_drvdata(pdev);++/* If slot is permanently frozen, turn everything off */+if(state==pci_channel_io_perm_failure){+sym2_remove(pdev);+returnPCI_ERS_RESULT_DISCONNECT;+}++init_completion(&np->s.io_reset_wait);+disable_irq(pdev->irq);+pci_disable_device(pdev);++/* Request a slot reset. */+returnPCI_ERS_RESULT_NEED_RESET;+}++/**+*sym2_io_slot_reset()--calledwhenthepcibushasbeenreset.+*@pdev:pointertoPCIdevice+*+*Restartthecardfromscratch.+*/+staticpci_ers_result_tsym2_io_slot_reset(structpci_dev*pdev)+{+structsym_hcb*np=pci_get_drvdata(pdev);++printk(KERN_INFO"%s: recovering from a PCI slot reset\n",+sym_name(np));++if(pci_enable_device(pdev)){+printk(KERN_ERR"%s: device setup failed most egregiously\n",+sym_name(np));+returnPCI_ERS_RESULT_DISCONNECT;+}++pci_set_master(pdev);+enable_irq(pdev->irq);++/* Perform host reset only on one instance of the card */+if(0==PCI_FUNC(pdev->devfn)){+if(sym_reset_scsi_bus(np,0)){+printk(KERN_ERR"%s: Unable to reset scsi host controller\n",+sym_name(np));+returnPCI_ERS_RESULT_DISCONNECT;+}+sym_start_up(np,1);+}++returnPCI_ERS_RESULT_RECOVERED;+}++/**+*sym2_io_resume()--resumenormalopsafterPCIreset+*@pdev:pointertoPCIdevice+*+*Calledwhentheerrorrecoverydrivertellsusthatits+*OKtoresumenormaloperation.Usecompletiontoallow+*haltedscsiopstoresume.+*/+staticvoidsym2_io_resume(structpci_dev*pdev)+{+structsym_hcb*np=pci_get_drvdata(pdev);+complete_all(&np->s.io_reset_wait);+}+staticvoidsym2_get_signalling(structScsi_Host*shost){structsym_hcb*np=sym_get_hcb(shost);
@@ -2809,6 +2811,14 @@ void sym_interrupt (struct sym_hcb *np)dstat|=INB(np,nc_dstat);istatc=INB(np,nc_istat);istat|=istatc;++/* Prevent deadlock waiting on a condition that may never clear. */+icnt++;+if(100<icnt){+if((np->s.device->error_state!=pci_channel_io_normal)+&&(np->s.device->error_state!=0))+return;+}}while(istatc&(SIP|DIP));if(DEBUG_FLAGS&DEBUG_TINY)
Matthew,
Second revised patch, based on comments from Luca and Randy.Dunlap
Please review, apply and forward upstream.
--linas
Various PCI bus errors can be signaled by newer PCI controllers.
This patch adds the PCI error recovery callbacks to the Symbios
SCSI device driver. The patch has been tested, and appears to
work well.
Signed-off-by: Linas Vepstas <redacted>
--
drivers/scsi/sym53c8xx_2/sym_glue.c | 99 ++++++++++++++++++++++++++++++++++++
drivers/scsi/sym53c8xx_2/sym_glue.h | 4 +
drivers/scsi/sym53c8xx_2/sym_hipd.c | 10 +++
3 files changed, 113 insertions(+)
Index: linux-2.6.18-rc7-git1/drivers/scsi/sym53c8xx_2/sym_glue.c
===================================================================
@@ -659,6 +659,11 @@ static irqreturn_t sym53c8xx_intr(int irif(DEBUG_FLAGS&DEBUG_TINY)printf_debug("[");+/* Avoid spinloop trying to handle interrupts on frozen device */+if((np->s.device->error_state!=pci_channel_io_normal)&&+(np->s.device->error_state!=0))+returnIRQ_HANDLED;+spin_lock_irqsave(np->s.host->host_lock,flags);sym_interrupt(np);spin_unlock_irqrestore(np->s.host->host_lock,flags);
@@ -726,6 +731,19 @@ static int sym_eh_handler(int op, char *dev_warn(&cmd->device->sdev_gendev,"%s operation started.\n",opname);+/* We may be in an error condition because the PCI bus+*wentdown.Inthiscase,weneedtowaituntilthe+*PCIbusisreset,thecardisreset,andonlythen+*proceedwiththescsierrorrecovery.There'sno+*pointinhurrying;takealeisurelywait.+*/+#define WAIT_FOR_PCI_RECOVERY 35+if((np->s.device->error_state!=pci_channel_io_normal)&&+(np->s.device->error_state!=0)&&+(wait_for_completion_timeout(&np->s.io_reset_wait,+WAIT_FOR_PCI_RECOVERY*HZ)==0))+returnSCSI_FAILED;+spin_lock_irq(host->host_lock);/* This one is queued in some place -> to wait for completion */FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq,qp){
@@ -1948,6 +1967,79 @@ static void __devexit sym2_remove(structattach_count--;}+/**+*sym2_io_error_detected()--calledwhenPCIerrorisdetected+*@pdev:pointertoPCIdevice+*@state:currentstateofthePCIslot+*/+staticpci_ers_result_tsym2_io_error_detected(structpci_dev*pdev,+enumpci_channel_statestate)+{+structsym_hcb*np=pci_get_drvdata(pdev);++/* If slot is permanently frozen, turn everything off */+if(state==pci_channel_io_perm_failure){+sym2_remove(pdev);+returnPCI_ERS_RESULT_DISCONNECT;+}++init_completion(&np->s.io_reset_wait);+disable_irq(pdev->irq);+pci_disable_device(pdev);++/* Request a slot reset. */+returnPCI_ERS_RESULT_NEED_RESET;+}++/**+*sym2_io_slot_reset()--calledwhenthepcibushasbeenreset.+*@pdev:pointertoPCIdevice+*+*Restartthecardfromscratch.+*/+staticpci_ers_result_tsym2_io_slot_reset(structpci_dev*pdev)+{+structsym_hcb*np=pci_get_drvdata(pdev);++printk(KERN_INFO"%s: recovering from a PCI slot reset\n",+sym_name(np));++if(pci_enable_device(pdev)){+printk(KERN_ERR"%s: device setup failed most egregiously\n",+sym_name(np));+returnPCI_ERS_RESULT_DISCONNECT;+}++pci_set_master(pdev);+enable_irq(pdev->irq);++/* Perform host reset only on one instance of the card */+if(PCI_FUNC(pdev->devfn)==0){+if(sym_reset_scsi_bus(np,0)){+printk(KERN_ERR"%s: Unable to reset scsi host controller\n",+sym_name(np));+returnPCI_ERS_RESULT_DISCONNECT;+}+sym_start_up(np,1);+}++returnPCI_ERS_RESULT_RECOVERED;+}++/**+*sym2_io_resume()--resumenormalopsafterPCIreset+*@pdev:pointertoPCIdevice+*+*Calledwhentheerrorrecoverydrivertellsusthatits+*OKtoresumenormaloperation.Usecompletiontoallow+*haltedscsiopstoresume.+*/+staticvoidsym2_io_resume(structpci_dev*pdev)+{+structsym_hcb*np=pci_get_drvdata(pdev);+complete_all(&np->s.io_reset_wait);+}+staticvoidsym2_get_signalling(structScsi_Host*shost){structsym_hcb*np=sym_get_hcb(shost);
@@ -2809,6 +2811,14 @@ void sym_interrupt (struct sym_hcb *np)dstat|=INB(np,nc_dstat);istatc=INB(np,nc_istat);istat|=istatc;++/* Prevent deadlock waiting on a condition that may never clear. */+icnt++;+if(icnt>100){+if((np->s.device->error_state!=pci_channel_io_normal)+&&(np->s.device->error_state!=0))+return;+}}while(istatc&(SIP|DIP));if(DEBUG_FLAGS&DEBUG_TINY)