diff options
author | Jiri Slaby <jirislaby@gmail.com> | 2006-12-08 05:39:13 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-08 11:28:59 -0500 |
commit | fc06b5cf858787934110b9398d2d5a0c0493c1dd (patch) | |
tree | b0c7b21e911039695149eb557397e27406c101cd | |
parent | 843b568cf0c800b87e48fcfb171a7a83318db39c (diff) |
[PATCH] Char: stallion, fix fail paths
Release everything what was allocated and check return value of isa probing.
Release only ISA boards in module exit, since pci have their own
pci-probing-remove.
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/char/stallion.c | 81 |
1 files changed, 52 insertions, 29 deletions
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 4ccf4a5834c9..7612464beeb1 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c | |||
@@ -143,6 +143,8 @@ static struct stlbrd *stl_brds[STL_MAXBRDS]; | |||
143 | * Not really much here! | 143 | * Not really much here! |
144 | */ | 144 | */ |
145 | #define BRD_FOUND 0x1 | 145 | #define BRD_FOUND 0x1 |
146 | #define STL_PROBED 0x2 | ||
147 | |||
146 | 148 | ||
147 | /* | 149 | /* |
148 | * Define the port structure istate flags. These set of flags are | 150 | * Define the port structure istate flags. These set of flags are |
@@ -2388,6 +2390,7 @@ static int __devinit stl_pciprobe(struct pci_dev *pdev, | |||
2388 | goto err_fr; | 2390 | goto err_fr; |
2389 | } | 2391 | } |
2390 | brdp->brdtype = brdtype; | 2392 | brdp->brdtype = brdtype; |
2393 | brdp->state |= STL_PROBED; | ||
2391 | 2394 | ||
2392 | /* | 2395 | /* |
2393 | * We have all resources from the board, so let's setup the actual | 2396 | * We have all resources from the board, so let's setup the actual |
@@ -4677,6 +4680,28 @@ static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack) | |||
4677 | } | 4680 | } |
4678 | } | 4681 | } |
4679 | 4682 | ||
4683 | static void stl_free_isabrds(void) | ||
4684 | { | ||
4685 | struct stlbrd *brdp; | ||
4686 | unsigned int i; | ||
4687 | |||
4688 | for (i = 0; i < stl_nrbrds; i++) { | ||
4689 | if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED)) | ||
4690 | continue; | ||
4691 | |||
4692 | free_irq(brdp->irq, brdp); | ||
4693 | |||
4694 | stl_cleanup_panels(brdp); | ||
4695 | |||
4696 | release_region(brdp->ioaddr1, brdp->iosize1); | ||
4697 | if (brdp->iosize2 > 0) | ||
4698 | release_region(brdp->ioaddr2, brdp->iosize2); | ||
4699 | |||
4700 | kfree(brdp); | ||
4701 | stl_brds[i] = NULL; | ||
4702 | } | ||
4703 | } | ||
4704 | |||
4680 | /* | 4705 | /* |
4681 | * Loadable module initialization stuff. | 4706 | * Loadable module initialization stuff. |
4682 | */ | 4707 | */ |
@@ -4684,7 +4709,8 @@ static int __init stallion_module_init(void) | |||
4684 | { | 4709 | { |
4685 | struct stlbrd *brdp; | 4710 | struct stlbrd *brdp; |
4686 | struct stlconf conf; | 4711 | struct stlconf conf; |
4687 | unsigned int i, retval; | 4712 | unsigned int i; |
4713 | int retval; | ||
4688 | 4714 | ||
4689 | printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion); | 4715 | printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion); |
4690 | 4716 | ||
@@ -4714,12 +4740,14 @@ static int __init stallion_module_init(void) | |||
4714 | } | 4740 | } |
4715 | 4741 | ||
4716 | retval = pci_register_driver(&stl_pcidriver); | 4742 | retval = pci_register_driver(&stl_pcidriver); |
4717 | if (retval) | 4743 | if (retval && stl_nrbrds == 0) |
4718 | goto err; | 4744 | goto err; |
4719 | 4745 | ||
4720 | stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS); | 4746 | stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS); |
4721 | if (!stl_serial) | 4747 | if (!stl_serial) { |
4722 | return -1; | 4748 | retval = -ENOMEM; |
4749 | goto err_pcidr; | ||
4750 | } | ||
4723 | 4751 | ||
4724 | /* | 4752 | /* |
4725 | * Set up a character driver for per board stuff. This is mainly used | 4753 | * Set up a character driver for per board stuff. This is mainly used |
@@ -4729,6 +4757,10 @@ static int __init stallion_module_init(void) | |||
4729 | printk("STALLION: failed to register serial board device\n"); | 4757 | printk("STALLION: failed to register serial board device\n"); |
4730 | 4758 | ||
4731 | stallion_class = class_create(THIS_MODULE, "staliomem"); | 4759 | stallion_class = class_create(THIS_MODULE, "staliomem"); |
4760 | if (IS_ERR(stallion_class)) { | ||
4761 | retval = PTR_ERR(stallion_class); | ||
4762 | goto err_reg; | ||
4763 | } | ||
4732 | for (i = 0; i < 4; i++) | 4764 | for (i = 0; i < 4; i++) |
4733 | class_device_create(stallion_class, NULL, | 4765 | class_device_create(stallion_class, NULL, |
4734 | MKDEV(STL_SIOMEMMAJOR, i), NULL, | 4766 | MKDEV(STL_SIOMEMMAJOR, i), NULL, |
@@ -4745,20 +4777,29 @@ static int __init stallion_module_init(void) | |||
4745 | stl_serial->flags = TTY_DRIVER_REAL_RAW; | 4777 | stl_serial->flags = TTY_DRIVER_REAL_RAW; |
4746 | tty_set_operations(stl_serial, &stl_ops); | 4778 | tty_set_operations(stl_serial, &stl_ops); |
4747 | 4779 | ||
4748 | if (tty_register_driver(stl_serial)) { | 4780 | retval = tty_register_driver(stl_serial); |
4749 | put_tty_driver(stl_serial); | 4781 | if (retval) { |
4750 | printk("STALLION: failed to register serial driver\n"); | 4782 | printk("STALLION: failed to register serial driver\n"); |
4751 | return -1; | 4783 | goto err_clsdev; |
4752 | } | 4784 | } |
4753 | 4785 | ||
4754 | return 0; | 4786 | return 0; |
4787 | err_clsdev: | ||
4788 | for (i = 0; i < 4; i++) | ||
4789 | class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i)); | ||
4790 | class_destroy(stallion_class); | ||
4791 | err_reg: | ||
4792 | unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"); | ||
4793 | put_tty_driver(stl_serial); | ||
4794 | err_pcidr: | ||
4795 | pci_unregister_driver(&stl_pcidriver); | ||
4796 | stl_free_isabrds(); | ||
4755 | err: | 4797 | err: |
4756 | return retval; | 4798 | return retval; |
4757 | } | 4799 | } |
4758 | 4800 | ||
4759 | static void __exit stallion_module_exit(void) | 4801 | static void __exit stallion_module_exit(void) |
4760 | { | 4802 | { |
4761 | struct stlbrd *brdp; | ||
4762 | int i; | 4803 | int i; |
4763 | 4804 | ||
4764 | pr_debug("cleanup_module()\n"); | 4805 | pr_debug("cleanup_module()\n"); |
@@ -4772,13 +4813,9 @@ static void __exit stallion_module_exit(void) | |||
4772 | * a hangup on every open port - to try to flush out any processes | 4813 | * a hangup on every open port - to try to flush out any processes |
4773 | * hanging onto ports. | 4814 | * hanging onto ports. |
4774 | */ | 4815 | */ |
4775 | i = tty_unregister_driver(stl_serial); | 4816 | tty_unregister_driver(stl_serial); |
4776 | put_tty_driver(stl_serial); | 4817 | put_tty_driver(stl_serial); |
4777 | if (i) { | 4818 | |
4778 | printk("STALLION: failed to un-register tty driver, " | ||
4779 | "errno=%d\n", -i); | ||
4780 | return; | ||
4781 | } | ||
4782 | for (i = 0; i < 4; i++) | 4819 | for (i = 0; i < 4; i++) |
4783 | class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i)); | 4820 | class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i)); |
4784 | if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"))) | 4821 | if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"))) |
@@ -4788,21 +4825,7 @@ static void __exit stallion_module_exit(void) | |||
4788 | 4825 | ||
4789 | pci_unregister_driver(&stl_pcidriver); | 4826 | pci_unregister_driver(&stl_pcidriver); |
4790 | 4827 | ||
4791 | for (i = 0; (i < stl_nrbrds); i++) { | 4828 | stl_free_isabrds(); |
4792 | if ((brdp = stl_brds[i]) == NULL) | ||
4793 | continue; | ||
4794 | |||
4795 | free_irq(brdp->irq, brdp); | ||
4796 | |||
4797 | stl_cleanup_panels(brdp); | ||
4798 | |||
4799 | release_region(brdp->ioaddr1, brdp->iosize1); | ||
4800 | if (brdp->iosize2 > 0) | ||
4801 | release_region(brdp->ioaddr2, brdp->iosize2); | ||
4802 | |||
4803 | kfree(brdp); | ||
4804 | stl_brds[i] = NULL; | ||
4805 | } | ||
4806 | } | 4829 | } |
4807 | 4830 | ||
4808 | module_init(stallion_module_init); | 4831 | module_init(stallion_module_init); |