aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sym53c8xx_2
diff options
context:
space:
mode:
authorTony Battersby <tonyb@cybernetics.com>2009-01-08 12:55:52 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-03-12 13:58:16 -0400
commita71d035de835caa7d14ef69928e0fde9fc241cc0 (patch)
treeeb44f1a045b1d7d8b762c19520437ce9e3a12179 /drivers/scsi/sym53c8xx_2
parentb409063a9b7a56c0d658feaffedeb74ad71edce7 (diff)
[SCSI] sym53c8xx: unmap pci memory after probe errors
During sym2_probe(), sym_init_device() does pci_iomap(), but there is no corresponding pci_iounmap() if an error occurs before sym_attach() copies sym_device::s.{ioaddr,ramaddr} to np. 1) Add the sym_iounmap_device() function. 2) Call sym_iounmap_device() if an error occurs between sym_init_device() and the time sym_attach() allocates np. 3) Make sym_attach() copy sym_device::s.{ioaddr,ramaddr} to np before calling any function that can fail so that sym_free_resources() will do the unmap instead of sym_iounmap_device(). Also fixed by this patch: During sym2_probe(), if sym_check_raid() returns nonzero, then pci_release_regions() is never called. Signed-off-by: Tony Battersby <tonyb@cybernetics.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/sym53c8xx_2')
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c66
1 files changed, 41 insertions, 25 deletions
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index a8ac60caadc0..8e69b5c35f58 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -1236,6 +1236,20 @@ static int sym53c8xx_proc_info(struct Scsi_Host *shost, char *buffer,
1236#endif /* SYM_LINUX_PROC_INFO_SUPPORT */ 1236#endif /* SYM_LINUX_PROC_INFO_SUPPORT */
1237 1237
1238/* 1238/*
1239 * Free resources claimed by sym_init_device(). Note that
1240 * sym_free_resources() should be used instead of this function after calling
1241 * sym_attach().
1242 */
1243static void __devinit
1244sym_iounmap_device(struct sym_device *device)
1245{
1246 if (device->s.ioaddr)
1247 pci_iounmap(device->pdev, device->s.ioaddr);
1248 if (device->s.ramaddr)
1249 pci_iounmap(device->pdev, device->s.ramaddr);
1250}
1251
1252/*
1239 * Free controller resources. 1253 * Free controller resources.
1240 */ 1254 */
1241static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev, 1255static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev,
@@ -1272,7 +1286,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
1272{ 1286{
1273 struct sym_data *sym_data; 1287 struct sym_data *sym_data;
1274 struct sym_hcb *np = NULL; 1288 struct sym_hcb *np = NULL;
1275 struct Scsi_Host *shost; 1289 struct Scsi_Host *shost = NULL;
1276 struct pci_dev *pdev = dev->pdev; 1290 struct pci_dev *pdev = dev->pdev;
1277 unsigned long flags; 1291 unsigned long flags;
1278 struct sym_fw *fw; 1292 struct sym_fw *fw;
@@ -1287,11 +1301,11 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
1287 */ 1301 */
1288 fw = sym_find_firmware(&dev->chip); 1302 fw = sym_find_firmware(&dev->chip);
1289 if (!fw) 1303 if (!fw)
1290 return NULL; 1304 goto attach_failed;
1291 1305
1292 shost = scsi_host_alloc(tpnt, sizeof(*sym_data)); 1306 shost = scsi_host_alloc(tpnt, sizeof(*sym_data));
1293 if (!shost) 1307 if (!shost)
1294 return NULL; 1308 goto attach_failed;
1295 sym_data = shost_priv(shost); 1309 sym_data = shost_priv(shost);
1296 1310
1297 /* 1311 /*
@@ -1321,6 +1335,13 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
1321 np->maxoffs = dev->chip.offset_max; 1335 np->maxoffs = dev->chip.offset_max;
1322 np->maxburst = dev->chip.burst_max; 1336 np->maxburst = dev->chip.burst_max;
1323 np->myaddr = dev->host_id; 1337 np->myaddr = dev->host_id;
1338 np->mmio_ba = (u32)dev->mmio_base;
1339 np->s.ioaddr = dev->s.ioaddr;
1340 np->s.ramaddr = dev->s.ramaddr;
1341 if (!(np->features & FE_RAM))
1342 dev->ram_base = 0;
1343 if (dev->ram_base)
1344 np->ram_ba = (u32)dev->ram_base;
1324 1345
1325 /* 1346 /*
1326 * Edit its name. 1347 * Edit its name.
@@ -1336,22 +1357,6 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
1336 goto attach_failed; 1357 goto attach_failed;
1337 } 1358 }
1338 1359
1339 /*
1340 * Try to map the controller chip to
1341 * virtual and physical memory.
1342 */
1343 np->mmio_ba = (u32)dev->mmio_base;
1344 np->s.ioaddr = dev->s.ioaddr;
1345 np->s.ramaddr = dev->s.ramaddr;
1346
1347 /*
1348 * Map on-chip RAM if present and supported.
1349 */
1350 if (!(np->features & FE_RAM))
1351 dev->ram_base = 0;
1352 if (dev->ram_base)
1353 np->ram_ba = (u32)dev->ram_base;
1354
1355 if (sym_hcb_attach(shost, fw, dev->nvram)) 1360 if (sym_hcb_attach(shost, fw, dev->nvram))
1356 goto attach_failed; 1361 goto attach_failed;
1357 1362
@@ -1419,12 +1424,13 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
1419 "TERMINATION, DEVICE POWER etc.!\n", sym_name(np)); 1424 "TERMINATION, DEVICE POWER etc.!\n", sym_name(np));
1420 spin_unlock_irqrestore(shost->host_lock, flags); 1425 spin_unlock_irqrestore(shost->host_lock, flags);
1421 attach_failed: 1426 attach_failed:
1422 if (!shost)
1423 return NULL;
1424 printf_info("sym%d: giving up ...\n", unit); 1427 printf_info("sym%d: giving up ...\n", unit);
1425 if (np) 1428 if (np)
1426 sym_free_resources(np, pdev, do_free_irq); 1429 sym_free_resources(np, pdev, do_free_irq);
1427 scsi_host_put(shost); 1430 else
1431 sym_iounmap_device(dev);
1432 if (shost)
1433 scsi_host_put(shost);
1428 1434
1429 return NULL; 1435 return NULL;
1430 } 1436 }
@@ -1700,6 +1706,8 @@ static int __devinit sym2_probe(struct pci_dev *pdev,
1700 struct sym_device sym_dev; 1706 struct sym_device sym_dev;
1701 struct sym_nvram nvram; 1707 struct sym_nvram nvram;
1702 struct Scsi_Host *shost; 1708 struct Scsi_Host *shost;
1709 int do_iounmap = 0;
1710 int do_disable_device = 1;
1703 1711
1704 memset(&sym_dev, 0, sizeof(sym_dev)); 1712 memset(&sym_dev, 0, sizeof(sym_dev));
1705 memset(&nvram, 0, sizeof(nvram)); 1713 memset(&nvram, 0, sizeof(nvram));
@@ -1713,11 +1721,15 @@ static int __devinit sym2_probe(struct pci_dev *pdev,
1713 goto disable; 1721 goto disable;
1714 1722
1715 sym_init_device(pdev, &sym_dev); 1723 sym_init_device(pdev, &sym_dev);
1724 do_iounmap = 1;
1725
1716 if (sym_check_supported(&sym_dev)) 1726 if (sym_check_supported(&sym_dev))
1717 goto free; 1727 goto free;
1718 1728
1719 if (sym_check_raid(&sym_dev)) 1729 if (sym_check_raid(&sym_dev)) {
1720 goto leave; /* Don't disable the device */ 1730 do_disable_device = 0; /* Don't disable the device */
1731 goto free;
1732 }
1721 1733
1722 if (sym_set_workarounds(&sym_dev)) 1734 if (sym_set_workarounds(&sym_dev))
1723 goto free; 1735 goto free;
@@ -1726,6 +1738,7 @@ static int __devinit sym2_probe(struct pci_dev *pdev,
1726 1738
1727 sym_get_nvram(&sym_dev, &nvram); 1739 sym_get_nvram(&sym_dev, &nvram);
1728 1740
1741 do_iounmap = 0; /* Don't sym_iounmap_device() after sym_attach(). */
1729 shost = sym_attach(&sym2_template, attach_count, &sym_dev); 1742 shost = sym_attach(&sym2_template, attach_count, &sym_dev);
1730 if (!shost) 1743 if (!shost)
1731 goto free; 1744 goto free;
@@ -1741,9 +1754,12 @@ static int __devinit sym2_probe(struct pci_dev *pdev,
1741 detach: 1754 detach:
1742 sym_detach(pci_get_drvdata(pdev), pdev); 1755 sym_detach(pci_get_drvdata(pdev), pdev);
1743 free: 1756 free:
1757 if (do_iounmap)
1758 sym_iounmap_device(&sym_dev);
1744 pci_release_regions(pdev); 1759 pci_release_regions(pdev);
1745 disable: 1760 disable:
1746 pci_disable_device(pdev); 1761 if (do_disable_device)
1762 pci_disable_device(pdev);
1747 leave: 1763 leave:
1748 return -ENODEV; 1764 return -ENODEV;
1749} 1765}