diff options
author | Jiri Slaby <jirislaby@gmail.com> | 2006-12-08 05:39:25 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-08 11:29:00 -0500 |
commit | f2362c9411e914642ffe216e10987bb9aae2a480 (patch) | |
tree | e703ac77ad75c8e69b56132827eed13f4943ad2a | |
parent | f1cc54f8c6ad76cf41e21cbb4620b9549b882a01 (diff) |
[PATCH] Char: istallion, change init sequence
Reorganizate module init and exit and implement logic, when something fails in
these functions. The former is needed for proper handling dynamic
tty_register_device.
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/istallion.c | 130 |
1 files changed, 75 insertions, 55 deletions
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 0f287f1b4342..a1755186f7b4 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
@@ -4545,46 +4545,49 @@ static const struct tty_operations stli_ops = { | |||
4545 | * Loadable module initialization stuff. | 4545 | * Loadable module initialization stuff. |
4546 | */ | 4546 | */ |
4547 | 4547 | ||
4548 | static void istallion_cleanup_isa(void) | ||
4549 | { | ||
4550 | struct stlibrd *brdp; | ||
4551 | unsigned int j; | ||
4552 | |||
4553 | for (j = 0; (j < stli_nrbrds); j++) { | ||
4554 | if ((brdp = stli_brds[j]) == NULL || (brdp->state & BST_PROBED)) | ||
4555 | continue; | ||
4556 | |||
4557 | stli_cleanup_ports(brdp); | ||
4558 | |||
4559 | iounmap(brdp->membase); | ||
4560 | if (brdp->iosize > 0) | ||
4561 | release_region(brdp->iobase, brdp->iosize); | ||
4562 | kfree(brdp); | ||
4563 | stli_brds[j] = NULL; | ||
4564 | } | ||
4565 | } | ||
4566 | |||
4548 | static int __init istallion_module_init(void) | 4567 | static int __init istallion_module_init(void) |
4549 | { | 4568 | { |
4550 | int i; | 4569 | unsigned int i; |
4570 | int retval; | ||
4551 | 4571 | ||
4552 | printk(KERN_INFO "%s: version %s\n", stli_drvtitle, stli_drvversion); | 4572 | printk(KERN_INFO "%s: version %s\n", stli_drvtitle, stli_drvversion); |
4553 | 4573 | ||
4554 | spin_lock_init(&stli_lock); | 4574 | spin_lock_init(&stli_lock); |
4555 | spin_lock_init(&brd_lock); | 4575 | spin_lock_init(&brd_lock); |
4556 | 4576 | ||
4557 | stli_initbrds(); | ||
4558 | |||
4559 | stli_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS); | ||
4560 | if (!stli_serial) | ||
4561 | return -ENOMEM; | ||
4562 | |||
4563 | /* | ||
4564 | * Allocate a temporary write buffer. | ||
4565 | */ | ||
4566 | stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL); | 4577 | stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL); |
4567 | if (!stli_txcookbuf) | 4578 | if (!stli_txcookbuf) { |
4568 | printk(KERN_ERR "STALLION: failed to allocate memory " | 4579 | printk(KERN_ERR "STALLION: failed to allocate memory " |
4569 | "(size=%d)\n", STLI_TXBUFSIZE); | 4580 | "(size=%d)\n", STLI_TXBUFSIZE); |
4581 | retval = -ENOMEM; | ||
4582 | goto err; | ||
4583 | } | ||
4570 | 4584 | ||
4571 | /* | 4585 | stli_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS); |
4572 | * Set up a character driver for the shared memory region. We need this | 4586 | if (!stli_serial) { |
4573 | * to down load the slave code image. Also it is a useful debugging tool. | 4587 | retval = -ENOMEM; |
4574 | */ | 4588 | goto err_free; |
4575 | if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem)) | 4589 | } |
4576 | printk(KERN_ERR "STALLION: failed to register serial memory " | ||
4577 | "device\n"); | ||
4578 | |||
4579 | istallion_class = class_create(THIS_MODULE, "staliomem"); | ||
4580 | for (i = 0; i < 4; i++) | ||
4581 | class_device_create(istallion_class, NULL, | ||
4582 | MKDEV(STL_SIOMEMMAJOR, i), | ||
4583 | NULL, "staliomem%d", i); | ||
4584 | 4590 | ||
4585 | /* | ||
4586 | * Set up the tty driver structure and register us as a driver. | ||
4587 | */ | ||
4588 | stli_serial->owner = THIS_MODULE; | 4591 | stli_serial->owner = THIS_MODULE; |
4589 | stli_serial->driver_name = stli_drvname; | 4592 | stli_serial->driver_name = stli_drvname; |
4590 | stli_serial->name = stli_serialname; | 4593 | stli_serial->name = stli_serialname; |
@@ -4596,58 +4599,75 @@ static int __init istallion_module_init(void) | |||
4596 | stli_serial->flags = TTY_DRIVER_REAL_RAW; | 4599 | stli_serial->flags = TTY_DRIVER_REAL_RAW; |
4597 | tty_set_operations(stli_serial, &stli_ops); | 4600 | tty_set_operations(stli_serial, &stli_ops); |
4598 | 4601 | ||
4599 | if (tty_register_driver(stli_serial)) { | 4602 | retval = tty_register_driver(stli_serial); |
4600 | put_tty_driver(stli_serial); | 4603 | if (retval) { |
4601 | printk(KERN_ERR "STALLION: failed to register serial driver\n"); | 4604 | printk(KERN_ERR "STALLION: failed to register serial driver\n"); |
4602 | return -EBUSY; | 4605 | goto err_ttyput; |
4606 | } | ||
4607 | |||
4608 | retval = stli_initbrds(); | ||
4609 | if (retval) | ||
4610 | goto err_ttyunr; | ||
4611 | |||
4612 | /* | ||
4613 | * Set up a character driver for the shared memory region. We need this | ||
4614 | * to down load the slave code image. Also it is a useful debugging tool. | ||
4615 | */ | ||
4616 | retval = register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem); | ||
4617 | if (retval) { | ||
4618 | printk(KERN_ERR "STALLION: failed to register serial memory " | ||
4619 | "device\n"); | ||
4620 | goto err_deinit; | ||
4603 | } | 4621 | } |
4622 | |||
4623 | istallion_class = class_create(THIS_MODULE, "staliomem"); | ||
4624 | for (i = 0; i < 4; i++) | ||
4625 | class_device_create(istallion_class, NULL, | ||
4626 | MKDEV(STL_SIOMEMMAJOR, i), | ||
4627 | NULL, "staliomem%d", i); | ||
4628 | |||
4604 | return 0; | 4629 | return 0; |
4630 | err_deinit: | ||
4631 | pci_unregister_driver(&stli_pcidriver); | ||
4632 | istallion_cleanup_isa(); | ||
4633 | err_ttyunr: | ||
4634 | tty_unregister_driver(stli_serial); | ||
4635 | err_ttyput: | ||
4636 | put_tty_driver(stli_serial); | ||
4637 | err_free: | ||
4638 | kfree(stli_txcookbuf); | ||
4639 | err: | ||
4640 | return retval; | ||
4605 | } | 4641 | } |
4606 | 4642 | ||
4607 | /*****************************************************************************/ | 4643 | /*****************************************************************************/ |
4608 | 4644 | ||
4609 | static void __exit istallion_module_exit(void) | 4645 | static void __exit istallion_module_exit(void) |
4610 | { | 4646 | { |
4611 | struct stlibrd *brdp; | ||
4612 | unsigned int j; | 4647 | unsigned int j; |
4613 | int i; | ||
4614 | 4648 | ||
4615 | printk(KERN_INFO "Unloading %s: version %s\n", stli_drvtitle, | 4649 | printk(KERN_INFO "Unloading %s: version %s\n", stli_drvtitle, |
4616 | stli_drvversion); | 4650 | stli_drvversion); |
4617 | 4651 | ||
4618 | pci_unregister_driver(&stli_pcidriver); | ||
4619 | /* | ||
4620 | * Free up all allocated resources used by the ports. This includes | ||
4621 | * memory and interrupts. | ||
4622 | */ | ||
4623 | if (stli_timeron) { | 4652 | if (stli_timeron) { |
4624 | stli_timeron = 0; | 4653 | stli_timeron = 0; |
4625 | del_timer_sync(&stli_timerlist); | 4654 | del_timer_sync(&stli_timerlist); |
4626 | } | 4655 | } |
4627 | 4656 | ||
4628 | i = tty_unregister_driver(stli_serial); | 4657 | unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"); |
4629 | put_tty_driver(stli_serial); | 4658 | |
4630 | for (j = 0; j < 4; j++) | 4659 | for (j = 0; j < 4; j++) |
4631 | class_device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, j)); | 4660 | class_device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, |
4661 | j)); | ||
4632 | class_destroy(istallion_class); | 4662 | class_destroy(istallion_class); |
4633 | if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"))) | ||
4634 | printk("STALLION: failed to un-register serial memory device, " | ||
4635 | "errno=%d\n", -i); | ||
4636 | |||
4637 | kfree(stli_txcookbuf); | ||
4638 | 4663 | ||
4639 | for (j = 0; (j < stli_nrbrds); j++) { | 4664 | pci_unregister_driver(&stli_pcidriver); |
4640 | if ((brdp = stli_brds[j]) == NULL || (brdp->state & BST_PROBED)) | 4665 | istallion_cleanup_isa(); |
4641 | continue; | ||
4642 | 4666 | ||
4643 | stli_cleanup_ports(brdp); | 4667 | tty_unregister_driver(stli_serial); |
4668 | put_tty_driver(stli_serial); | ||
4644 | 4669 | ||
4645 | iounmap(brdp->membase); | 4670 | kfree(stli_txcookbuf); |
4646 | if (brdp->iosize > 0) | ||
4647 | release_region(brdp->iobase, brdp->iosize); | ||
4648 | kfree(brdp); | ||
4649 | stli_brds[j] = NULL; | ||
4650 | } | ||
4651 | } | 4671 | } |
4652 | 4672 | ||
4653 | module_init(istallion_module_init); | 4673 | module_init(istallion_module_init); |