[SCSI] sym53c8xx: fix bogus free_irq() on error path
authorTony Battersby <tonyb@cybernetics.com>
Thu, 8 Jan 2009 17:54:45 +0000 (12:54 -0500)
committerJames Bottomley <James.Bottomley@HansenPartnership.com>
Thu, 12 Mar 2009 17:58:16 +0000 (12:58 -0500)
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>
drivers/scsi/sym53c8xx_2/sym_glue.c

index cef03e7..a8ac60c 100644 (file)
@@ -1238,12 +1238,13 @@ static int sym53c8xx_proc_info(struct Scsi_Host *shost, char *buffer,
 /*
  *     Free controller resources.
  */
-static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev)
+static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev,
+               int do_free_irq)
 {
        /*
         *  Free O/S specific resources.
         */
-       if (pdev->irq)
+       if (do_free_irq)
                free_irq(pdev->irq, np->s.host);
        if (np->s.ioaddr)
                pci_iounmap(pdev, np->s.ioaddr);
@@ -1275,6 +1276,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
        struct pci_dev *pdev = dev->pdev;
        unsigned long flags;
        struct sym_fw *fw;
+       int do_free_irq = 0;
 
        printk(KERN_INFO "sym%d: <%s> rev 0x%x at pci %s irq %u\n",
                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,
                        sym_name(np), pdev->irq);
                goto attach_failed;
        }
+       do_free_irq = 1;
 
        /*
         *  After SCSI devices have been opened, we cannot
@@ -1420,7 +1423,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
                return NULL;
        printf_info("sym%d: giving up ...\n", unit);
        if (np)
-               sym_free_resources(np, pdev);
+               sym_free_resources(np, pdev, do_free_irq);
        scsi_host_put(shost);
 
        return NULL;
@@ -1659,7 +1662,7 @@ static int sym_detach(struct Scsi_Host *shost, struct pci_dev *pdev)
        udelay(10);
        OUTB(np, nc_istat, 0);
 
-       sym_free_resources(np, pdev);
+       sym_free_resources(np, pdev, 1);
        scsi_host_put(shost);
 
        return 1;