diff options
author | Tony Battersby <tonyb@cybernetics.com> | 2009-01-08 12:54:45 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-03-12 13:58:16 -0400 |
commit | b409063a9b7a56c0d658feaffedeb74ad71edce7 (patch) | |
tree | 9cce185196e88f961e1cf5c24253ae84098b8822 /drivers/scsi | |
parent | 07b9d81e849f64b990e943de6ad75b63dafe5a4b (diff) |
[SCSI] sym53c8xx: fix bogus free_irq() on error path
If sym_attach() gets an error at or before request_irq(), then
sym_free_resources() will call free_irq() for an unregistered
interrupt handler.
Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/sym53c8xx_2/sym_glue.c | 11 |
1 files changed, 7 insertions, 4 deletions
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index cef03e768367..a8ac60caadc0 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c | |||
@@ -1238,12 +1238,13 @@ static int sym53c8xx_proc_info(struct Scsi_Host *shost, char *buffer, | |||
1238 | /* | 1238 | /* |
1239 | * Free controller resources. | 1239 | * Free controller resources. |
1240 | */ | 1240 | */ |
1241 | static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev) | 1241 | static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev, |
1242 | int do_free_irq) | ||
1242 | { | 1243 | { |
1243 | /* | 1244 | /* |
1244 | * Free O/S specific resources. | 1245 | * Free O/S specific resources. |
1245 | */ | 1246 | */ |
1246 | if (pdev->irq) | 1247 | if (do_free_irq) |
1247 | free_irq(pdev->irq, np->s.host); | 1248 | free_irq(pdev->irq, np->s.host); |
1248 | if (np->s.ioaddr) | 1249 | if (np->s.ioaddr) |
1249 | pci_iounmap(pdev, np->s.ioaddr); | 1250 | pci_iounmap(pdev, np->s.ioaddr); |
@@ -1275,6 +1276,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, | |||
1275 | struct pci_dev *pdev = dev->pdev; | 1276 | struct pci_dev *pdev = dev->pdev; |
1276 | unsigned long flags; | 1277 | unsigned long flags; |
1277 | struct sym_fw *fw; | 1278 | struct sym_fw *fw; |
1279 | int do_free_irq = 0; | ||
1278 | 1280 | ||
1279 | printk(KERN_INFO "sym%d: <%s> rev 0x%x at pci %s irq %u\n", | 1281 | printk(KERN_INFO "sym%d: <%s> rev 0x%x at pci %s irq %u\n", |
1280 | unit, dev->chip.name, pdev->revision, pci_name(pdev), | 1282 | unit, dev->chip.name, pdev->revision, pci_name(pdev), |
@@ -1364,6 +1366,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, | |||
1364 | sym_name(np), pdev->irq); | 1366 | sym_name(np), pdev->irq); |
1365 | goto attach_failed; | 1367 | goto attach_failed; |
1366 | } | 1368 | } |
1369 | do_free_irq = 1; | ||
1367 | 1370 | ||
1368 | /* | 1371 | /* |
1369 | * After SCSI devices have been opened, we cannot | 1372 | * After SCSI devices have been opened, we cannot |
@@ -1420,7 +1423,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, | |||
1420 | return NULL; | 1423 | return NULL; |
1421 | printf_info("sym%d: giving up ...\n", unit); | 1424 | printf_info("sym%d: giving up ...\n", unit); |
1422 | if (np) | 1425 | if (np) |
1423 | sym_free_resources(np, pdev); | 1426 | sym_free_resources(np, pdev, do_free_irq); |
1424 | scsi_host_put(shost); | 1427 | scsi_host_put(shost); |
1425 | 1428 | ||
1426 | return NULL; | 1429 | return NULL; |
@@ -1659,7 +1662,7 @@ static int sym_detach(struct Scsi_Host *shost, struct pci_dev *pdev) | |||
1659 | udelay(10); | 1662 | udelay(10); |
1660 | OUTB(np, nc_istat, 0); | 1663 | OUTB(np, nc_istat, 0); |
1661 | 1664 | ||
1662 | sym_free_resources(np, pdev); | 1665 | sym_free_resources(np, pdev, 1); |
1663 | scsi_host_put(shost); | 1666 | scsi_host_put(shost); |
1664 | 1667 | ||
1665 | return 1; | 1668 | return 1; |