+ char-stallion-implement-fail-paths.patch added to -mm tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The patch titled
     Char: stallion, implement fail paths
has been added to the -mm tree.  Its filename is
     char-stallion-implement-fail-paths.patch

See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find
out what to do about this

------------------------------------------------------
Subject: Char: stallion, implement fail paths
From: Jiri Slaby <jirislaby@xxxxxxxxx>

This driver expect everything to work.  Implement fail paths logic to release
regions, irq hangler, memory...  if something is in bad state.

Signed-off-by: Jiri Slaby <jirislaby@xxxxxxxxx>
Cc: Alan Cox <alan@xxxxxxxxxxxxxxxxxxx>
Signed-off-by: Andrew Morton <akpm@xxxxxxxx>
---

 drivers/char/stallion.c |  199 ++++++++++++++++++++++++--------------
 1 file changed, 128 insertions(+), 71 deletions(-)

diff -puN drivers/char/stallion.c~char-stallion-implement-fail-paths drivers/char/stallion.c
--- a/drivers/char/stallion.c~char-stallion-implement-fail-paths
+++ a/drivers/char/stallion.c
@@ -779,7 +779,8 @@ static void __init stl_argbrds(void)
 		brdp->ioaddr2 = conf.ioaddr2;
 		brdp->irq = conf.irq;
 		brdp->irqtype = conf.irqtype;
-		stl_brdinit(brdp);
+		if (stl_brdinit(brdp))
+			kfree(brdp);
 	}
 }
 
@@ -1967,6 +1968,29 @@ static int __init stl_initports(struct s
 	return(0);
 }
 
+static void stl_cleanup_panels(struct stlbrd *brdp)
+{
+	struct stlpanel *panelp;
+	struct stlport *portp;
+	unsigned int j, k;
+
+	for (j = 0; j < STL_MAXPANELS; j++) {
+		panelp = brdp->panels[j];
+		if (panelp == NULL)
+			continue;
+		for (k = 0; k < STL_PORTSPERPANEL; k++) {
+			portp = panelp->ports[k];
+			if (portp == NULL)
+				continue;
+			if (portp->tty != NULL)
+				stl_hangup(portp->tty);
+			kfree(portp->tx.buf);
+			kfree(portp);
+		}
+		kfree(panelp);
+	}
+}
+
 /*****************************************************************************/
 
 /*
@@ -1978,7 +2002,7 @@ static int __init stl_initeio(struct stl
 	struct stlpanel	*panelp;
 	unsigned int	status;
 	char		*name;
-	int		rc;
+	int		retval;
 
 	pr_debug("stl_initeio(brdp=%p)\n", brdp);
 
@@ -2005,18 +2029,20 @@ static int __init stl_initeio(struct stl
 		    (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
 			printk("STALLION: invalid irq=%d for brd=%d\n",
 				brdp->irq, brdp->brdnr);
-			return(-EINVAL);
+			retval = -EINVAL;
+			goto err;
 		}
 		outb((stl_vecmap[brdp->irq] | EIO_0WS |
 			((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
 			brdp->ioctrl);
 	}
 
+	retval = -EBUSY;
 	if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
 		printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
 			"%x conflicts with another device\n", brdp->brdnr, 
 			brdp->ioaddr1);
-		return(-EBUSY);
+		goto err;
 	}
 	
 	if (brdp->iosize2 > 0)
@@ -2027,8 +2053,7 @@ static int __init stl_initeio(struct stl
 			printk(KERN_WARNING "STALLION: Warning, also "
 				"releasing board %d I/O address %x \n", 
 				brdp->brdnr, brdp->ioaddr1);
-			release_region(brdp->ioaddr1, brdp->iosize1);
-        		return(-EBUSY);
+			goto err_rel1;
 		}
 
 /*
@@ -2037,6 +2062,7 @@ static int __init stl_initeio(struct stl
 	brdp->clk = CD1400_CLK;
 	brdp->isr = stl_eiointr;
 
+	retval = -ENODEV;
 	switch (status & EIO_IDBITMASK) {
 	case EIO_8PORTM:
 		brdp->clk = CD1400_CLK8M;
@@ -2060,11 +2086,11 @@ static int __init stl_initeio(struct stl
 			brdp->nrports = 16;
 			break;
 		default:
-			return(-ENODEV);
+			goto err_rel2;
 		}
 		break;
 	default:
-		return(-ENODEV);
+		goto err_rel2;
 	}
 
 /*
@@ -2076,7 +2102,8 @@ static int __init stl_initeio(struct stl
 	if (!panelp) {
 		printk(KERN_WARNING "STALLION: failed to allocate memory "
 			"(size=%Zd)\n", sizeof(struct stlpanel));
-		return -ENOMEM;
+		retval = -ENOMEM;
+		goto err_rel2;
 	}
 
 	panelp->magic = STL_PANELMAGIC;
@@ -2100,11 +2127,20 @@ static int __init stl_initeio(struct stl
 	if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
 		printk("STALLION: failed to register interrupt "
 		    "routine for %s irq=%d\n", name, brdp->irq);
-		rc = -ENODEV;
-	} else {
-		rc = 0;
+		retval = -ENODEV;
+		goto err_fr;
 	}
-	return rc;
+
+	return 0;
+err_fr:
+	stl_cleanup_panels(brdp);
+err_rel2:
+	if (brdp->iosize2 > 0)
+		release_region(brdp->ioaddr2, brdp->iosize2);
+err_rel1:
+	release_region(brdp->ioaddr1, brdp->iosize1);
+err:
+	return retval;
 }
 
 /*****************************************************************************/
@@ -2118,7 +2154,7 @@ static int __init stl_initech(struct stl
 {
 	struct stlpanel	*panelp;
 	unsigned int	status, nxtid, ioaddr, conflict;
-	int		panelnr, banknr, i;
+	int		panelnr, banknr, i, retval;
 	char		*name;
 
 	pr_debug("stl_initech(brdp=%p)\n", brdp);
@@ -2138,13 +2174,16 @@ static int __init stl_initech(struct stl
 		brdp->ioctrl = brdp->ioaddr1 + 1;
 		brdp->iostatus = brdp->ioaddr1 + 1;
 		status = inb(brdp->iostatus);
-		if ((status & ECH_IDBITMASK) != ECH_ID)
-			return(-ENODEV);
+		if ((status & ECH_IDBITMASK) != ECH_ID) {
+			retval = -ENODEV;
+			goto err;
+		}
 		if ((brdp->irq < 0) || (brdp->irq > 15) ||
 		    (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
 			printk("STALLION: invalid irq=%d for brd=%d\n",
 				brdp->irq, brdp->brdnr);
-			return(-EINVAL);
+			retval = -EINVAL;
+			goto err;
 		}
 		status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
 		status |= (stl_vecmap[brdp->irq] << 1);
@@ -2164,13 +2203,16 @@ static int __init stl_initech(struct stl
 		brdp->ioctrl = brdp->ioaddr1 + 0x20;
 		brdp->iostatus = brdp->ioctrl;
 		status = inb(brdp->iostatus);
-		if ((status & ECH_IDBITMASK) != ECH_ID)
-			return(-ENODEV);
+		if ((status & ECH_IDBITMASK) != ECH_ID) {
+			retval = -ENODEV;
+			goto err;
+		}
 		if ((brdp->irq < 0) || (brdp->irq > 15) ||
 		    (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
 			printk("STALLION: invalid irq=%d for brd=%d\n",
 				brdp->irq, brdp->brdnr);
-			return(-EINVAL);
+			retval = -EINVAL;
+			goto err;
 		}
 		outb(ECHMC_BRDRESET, brdp->ioctrl);
 		outb(ECHMC_INTENABLE, brdp->ioctrl);
@@ -2197,19 +2239,20 @@ static int __init stl_initech(struct stl
 
 	default:
 		printk("STALLION: unknown board type=%d\n", brdp->brdtype);
-		return(-EINVAL);
-		break;
+		retval = -EINVAL;
+		goto err;
 	}
 
 /*
  *	Check boards for possible IO address conflicts and return fail status 
  * 	if an IO conflict found.
  */
+	retval = -EBUSY;
 	if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
 		printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
 			"%x conflicts with another device\n", brdp->brdnr, 
 			brdp->ioaddr1);
-		return(-EBUSY);
+		goto err;
 	}
 	
 	if (brdp->iosize2 > 0)
@@ -2220,8 +2263,7 @@ static int __init stl_initech(struct stl
 			printk(KERN_WARNING "STALLION: Warning, also "
 				"releasing board %d I/O address %x \n", 
 				brdp->brdnr, brdp->ioaddr1);
-			release_region(brdp->ioaddr1, brdp->iosize1);
-			return(-EBUSY);
+			goto err_rel1;
 		}
 
 /*
@@ -2243,12 +2285,12 @@ static int __init stl_initech(struct stl
 		}
 		status = inb(ioaddr + ECH_PNLSTATUS);
 		if ((status & ECH_PNLIDMASK) != nxtid)
-			break;
+			goto err_fr;
 		panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
 		if (!panelp) {
 			printk("STALLION: failed to allocate memory "
 				"(size=%Zd)\n", sizeof(struct stlpanel));
-			break;
+			goto err_fr;
 		}
 		panelp->magic = STL_PANELMAGIC;
 		panelp->brdnr = brdp->brdnr;
@@ -2296,7 +2338,7 @@ static int __init stl_initech(struct stl
 		brdp->panels[panelnr++] = panelp;
 		if ((brdp->brdtype != BRD_ECHPCI) &&
 		    (ioaddr >= (brdp->ioaddr2 + brdp->iosize2)))
-			break;
+			goto err_fr;
 	}
 
 	brdp->nrpanels = panelnr;
@@ -2308,12 +2350,19 @@ static int __init stl_initech(struct stl
 	if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
 		printk("STALLION: failed to register interrupt "
 		    "routine for %s irq=%d\n", name, brdp->irq);
-		i = -ENODEV;
-	} else {
-		i = 0;
+		retval = -ENODEV;
+		goto err_fr;
 	}
 
-	return(i);
+	return 0;
+err_fr:
+	stl_cleanup_panels(brdp);
+	if (brdp->iosize2 > 0)
+		release_region(brdp->ioaddr2, brdp->iosize2);
+err_rel1:
+	release_region(brdp->ioaddr1, brdp->iosize1);
+err:
+	return retval;
 }
 
 /*****************************************************************************/
@@ -2327,25 +2376,30 @@ static int __init stl_initech(struct stl
 
 static int __init stl_brdinit(struct stlbrd *brdp)
 {
-	int	i;
+	int i, retval;
 
 	pr_debug("stl_brdinit(brdp=%p)\n", brdp);
 
 	switch (brdp->brdtype) {
 	case BRD_EASYIO:
 	case BRD_EASYIOPCI:
-		stl_initeio(brdp);
+		retval = stl_initeio(brdp);
+		if (retval)
+			goto err;
 		break;
 	case BRD_ECH:
 	case BRD_ECHMC:
 	case BRD_ECHPCI:
 	case BRD_ECH64PCI:
-		stl_initech(brdp);
+		retval = stl_initech(brdp);
+		if (retval)
+			goto err;
 		break;
 	default:
 		printk("STALLION: board=%d is unknown board type=%d\n",
 			brdp->brdnr, brdp->brdtype);
-		return(ENODEV);
+		retval = -ENODEV;
+		goto err;
 	}
 
 	stl_brds[brdp->brdnr] = brdp;
@@ -2353,7 +2407,7 @@ static int __init stl_brdinit(struct stl
 		printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
 			stl_brdnames[brdp->brdtype], brdp->brdnr,
 			brdp->ioaddr1, brdp->irq);
-		return(ENODEV);
+		goto err_free;
 	}
 
 	for (i = 0; (i < STL_MAXPANELS); i++)
@@ -2364,7 +2418,20 @@ static int __init stl_brdinit(struct stl
 		"nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
 		brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
 		brdp->nrports);
-	return(0);
+
+	return 0;
+err_free:
+	free_irq(brdp->irq, brdp);
+
+	stl_cleanup_panels(brdp);
+
+	release_region(brdp->ioaddr1, brdp->iosize1);
+	if (brdp->iosize2 > 0)
+		release_region(brdp->ioaddr2, brdp->iosize2);
+
+	stl_brds[brdp->brdnr] = NULL;
+err:
+	return retval;
 }
 
 /*****************************************************************************/
@@ -2387,29 +2454,6 @@ static int __init stl_getbrdnr(void)
 	return(-1);
 }
 
-static void stl_cleanup_panels(struct stlbrd *brdp)
-{
-	struct stlpanel *panelp;
-	struct stlport *portp;
-	unsigned int j, k;
-
-	for (j = 0; j < STL_MAXPANELS; j++) {
-		panelp = brdp->panels[j];
-		if (panelp == NULL)
-			continue;
-		for (k = 0; k < STL_PORTSPERPANEL; k++) {
-			portp = panelp->ports[k];
-			if (portp == NULL)
-				continue;
-			if (portp->tty != NULL)
-				stl_hangup(portp->tty);
-			kfree(portp->tx.buf);
-			kfree(portp);
-		}
-		kfree(panelp);
-	}
-}
-
 /*****************************************************************************/
 /*
  *	We have a Stallion board. Allocate a board structure and
@@ -2422,21 +2466,27 @@ static int __devinit stl_pciprobe(struct
 {
 	struct stlbrd *brdp;
 	unsigned int brdtype = ent->driver_data;
+	int retval = -ENODEV;
 
 	if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
-		return -ENODEV;
+		goto err;
 
 	dev_info(&pdev->dev, "please, report this to LKML: %x/%x/%x\n",
 			pdev->vendor, pdev->device, pdev->class);
 
-	if (pci_enable_device(pdev))
-		return(-EIO);
-	if ((brdp = stl_allocbrd()) == NULL)
-		return(-ENOMEM);
-	if ((brdp->brdnr = stl_getbrdnr()) < 0) {
+	retval = pci_enable_device(pdev);
+	if (retval)
+		goto err;
+	brdp = stl_allocbrd();
+	if (brdp == NULL) {
+		retval = -ENOMEM;
+		goto err;
+	}
+	brdp->brdnr = stl_getbrdnr();
+	if (brdp->brdnr < 0) {
 		dev_err(&pdev->dev, "too many boards found, "
 			"maximum supported %d\n", STL_MAXBRDS);
-		return(0);
+		goto err_fr;
 	}
 	brdp->brdtype = brdtype;
 
@@ -2463,11 +2513,17 @@ static int __devinit stl_pciprobe(struct
 	}
 
 	brdp->irq = pdev->irq;
-	stl_brdinit(brdp);
+	retval = stl_brdinit(brdp);
+	if (retval)
+		goto err_fr;
 
 	pci_set_drvdata(pdev, brdp);
 
-	return(0);
+	return 0;
+err_fr:
+	kfree(brdp);
+err:
+	return retval;
 }
 
 static void __devexit stl_pciremove(struct pci_dev *pdev)
@@ -2530,7 +2586,8 @@ static int __init stl_initbrds(void)
 		brdp->ioaddr2 = confp->ioaddr2;
 		brdp->irq = confp->irq;
 		brdp->irqtype = confp->irqtype;
-		stl_brdinit(brdp);
+		if (stl_brdinit(brdp))
+			kfree(brdp);
 	}
 
 /*
_

Patches currently in -mm which might be from jirislaby@xxxxxxxxx are

char-correct-pci_get_device-changes.patch
mxser-correct-tty-driver-name.patch
pci-mxser-pci-refcounts.patch
mxser-make-an-experimental-clone.patch
char-mxser_new-correct-include-file.patch
char-mxser_new-upgrade-to-191.patch
char-mxser_new-rework-to-allow-dynamic-structs.patch
char-mxser_new-use-__devinit-macros.patch
char-mxser_new-pci_request_region-for-pci-regions.patch
char-mxser_new-check-request_region-retvals.patch
char-mxser_new-kill-unneeded-memsets.patch
char-mxser_new-revert-spin_lock-changes.patch
char-mxser_new-remove-request-for-testers-line.patch
char-mxser_new-debug-printk-dependent-on-debug.patch
char-mxser_new-alter-license-terms.patch
char-mxser_new-code-upside-down.patch
char-mxser_new-cmspar-is-defined.patch
char-remove-unneded-termbits-redefinitions-mxser_new.patch
char-mxser_new-eliminate-tty-ldisc-deref.patch
char-mxser_new-testbit-for-bit-testing.patch
char-mxser_new-correct-fail-paths.patch
char-mxser_new-dont-check-tty_unregister-retval.patch
char-mxser_new-compress-isa-finding.patch
char-mxser_new-register-tty-devices-on-the-fly.patch
char-mxser_new-compact-structures-round2.patch
char-mxser_new-reverse-if-else-paths-patch.patch
char-mxser_new-comments-cleanup.patch
char-mxser_new-correct-intr-handler-proto.patch
char-mxser_new-delete-ttys-and-termios.patch
char-mxser_new-pci-probing.patch
char-mxser_new-clean-macros.patch
maintainers-add-me-to-isicom-mxser.patch
mxser_new-correct-tty-driver-name.patch
char-stallion-use-pr_debug-macro.patch
char-stallion-remove-unneeded-casts.patch
char-stallion-kill-typedefs.patch
char-stallion-move-init-deinit.patch
char-stallion-uninline-functions.patch
char-stallion-mark-functions-as-init.patch
char-stallion-remove-many-prototypes.patch
char-isicom-expand-function.patch
char-isicom-rename-init-function.patch
char-isicom-remove-isa-code.patch
char-isicom-remove-unneeded-memset.patch
char-isicom-move-to-tty_register_device.patch
char-isicom-use-pci_request_region.patch
char-isicom-check-kmalloc-retval.patch
char-isicom-use-completion.patch
char-isicom-simplify-timer.patch
char-isicom-remove-cvs-stuff.patch
char-sx-convert-to-pci-probing.patch
char-sx-use-kcalloc.patch
char-sx-mark-functions-as-devinit.patch
char-sx-use-eisa-probing.patch
char-sx-ifdef-isa-code.patch
char-stallion-convert-to-pci-probing.patch
char-stallion-prints-cleanup.patch
char-stallion-implement-fail-paths.patch
char-stallion-correct-__init-macros.patch

-
To unsubscribe from this list: send the line "unsubscribe mm-commits" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Kernel Newbies FAQ]     [Kernel Archive]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Photo]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]

  Powered by Linux