aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorKrzysztof Helt <krzysztof.h1@wp.pl>2008-01-11 15:50:46 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-01-23 12:29:25 -0500
commitd9aa3af09cdc5d3ae0e67bed4107bcf7e25b9f31 (patch)
tree82d2699430907da4947022c406feabf855414bdf /drivers
parent3a0086a80ab7c2f1adb0e9b2a6fc82632979cec5 (diff)
[SCSI] sym53c8xx: fixes two bugs related to chip reset
This patch fixes two bugs pointed by James Bottomley: 1. the if (!sym_data->io_reset). That variable is only ever filled by a stack based completion. If we find it non empty it means this code has been entered twice and we have a severe problem, so that should just become a BUG_ON(sym_data->io_reset). 2. sym_data->io_reset should be set to NULL before the routine is exited otherwise the PCI recovery code could end up completing what will be a bogus pointer into the stack. Big thanks to James Bottomley for help with the patch. Signed-off-by: Krzysztof Helt <krzysztof.h1@w.pl> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c13
1 files changed, 7 insertions, 6 deletions
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 09bbb39efe88..dc9af8f8f260 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -609,22 +609,24 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
609 */ 609 */
610#define WAIT_FOR_PCI_RECOVERY 35 610#define WAIT_FOR_PCI_RECOVERY 35
611 if (pci_channel_offline(pdev)) { 611 if (pci_channel_offline(pdev)) {
612 struct completion *io_reset;
613 int finished_reset = 0; 612 int finished_reset = 0;
614 init_completion(&eh_done); 613 init_completion(&eh_done);
615 spin_lock_irq(shost->host_lock); 614 spin_lock_irq(shost->host_lock);
616 /* Make sure we didn't race */ 615 /* Make sure we didn't race */
617 if (pci_channel_offline(pdev)) { 616 if (pci_channel_offline(pdev)) {
618 if (!sym_data->io_reset) 617 BUG_ON(sym_data->io_reset);
619 sym_data->io_reset = &eh_done; 618 sym_data->io_reset = &eh_done;
620 io_reset = sym_data->io_reset;
621 } else { 619 } else {
622 finished_reset = 1; 620 finished_reset = 1;
623 } 621 }
624 spin_unlock_irq(shost->host_lock); 622 spin_unlock_irq(shost->host_lock);
625 if (!finished_reset) 623 if (!finished_reset)
626 finished_reset = wait_for_completion_timeout(io_reset, 624 finished_reset = wait_for_completion_timeout
625 (sym_data->io_reset,
627 WAIT_FOR_PCI_RECOVERY*HZ); 626 WAIT_FOR_PCI_RECOVERY*HZ);
627 spin_lock_irq(shost->host_lock);
628 sym_data->io_reset = NULL;
629 spin_unlock_irq(shost->host_lock);
628 if (!finished_reset) 630 if (!finished_reset)
629 return SCSI_FAILED; 631 return SCSI_FAILED;
630 } 632 }
@@ -1879,7 +1881,6 @@ static void sym2_io_resume(struct pci_dev *pdev)
1879 spin_lock_irq(shost->host_lock); 1881 spin_lock_irq(shost->host_lock);
1880 if (sym_data->io_reset) 1882 if (sym_data->io_reset)
1881 complete_all(sym_data->io_reset); 1883 complete_all(sym_data->io_reset);
1882 sym_data->io_reset = NULL;
1883 spin_unlock_irq(shost->host_lock); 1884 spin_unlock_irq(shost->host_lock);
1884} 1885}
1885 1886