aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Slaby <jirislaby@gmail.com>2006-12-08 05:39:25 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-08 11:29:00 -0500
commitf2362c9411e914642ffe216e10987bb9aae2a480 (patch)
treee703ac77ad75c8e69b56132827eed13f4943ad2a
parentf1cc54f8c6ad76cf41e21cbb4620b9549b882a01 (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.c130
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
4548static 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
4548static int __init istallion_module_init(void) 4567static 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;
4630err_deinit:
4631 pci_unregister_driver(&stli_pcidriver);
4632 istallion_cleanup_isa();
4633err_ttyunr:
4634 tty_unregister_driver(stli_serial);
4635err_ttyput:
4636 put_tty_driver(stli_serial);
4637err_free:
4638 kfree(stli_txcookbuf);
4639err:
4640 return retval;
4605} 4641}
4606 4642
4607/*****************************************************************************/ 4643/*****************************************************************************/
4608 4644
4609static void __exit istallion_module_exit(void) 4645static 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
4653module_init(istallion_module_init); 4673module_init(istallion_module_init);