[PATCH 3/5] Char: istallion, change init sequence

From: Jiri Slaby
Date: Sat Nov 11 2006 - 16:49:16 EST


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@xxxxxxxxx>

---
commit 92452a22c4ada362e991cbf0de84c8914525672a
tree 6e6dc05ce30f3cf7f159842136f96b2009dbbaa1
parent d804883791d787b9c0bc0b79ccec78d0d20d850d
author Jiri Slaby <jirislaby@xxxxxxxxx> Sat, 11 Nov 2006 02:17:14 +0100
committer Jiri Slaby <jirislaby@xxxxxxxxx> Sat, 11 Nov 2006 22:23:35 +0100

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 2de677f..bf58938 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -4545,46 +4545,49 @@ static const struct tty_operations stli_
* Loadable module initialization stuff.
*/

+static void istallion_cleanup_isa(void)
+{
+ struct stlibrd *brdp;
+ unsigned int j;
+
+ for (j = 0; (j < stli_nrbrds); j++) {
+ if ((brdp = stli_brds[j]) == NULL || (brdp->state & BST_PROBED))
+ continue;
+
+ stli_cleanup_ports(brdp);
+
+ iounmap(brdp->membase);
+ if (brdp->iosize > 0)
+ release_region(brdp->iobase, brdp->iosize);
+ kfree(brdp);
+ stli_brds[j] = NULL;
+ }
+}
+
static int __init istallion_module_init(void)
{
- int i;
+ unsigned int i;
+ int retval;

printk(KERN_INFO "%s: version %s\n", stli_drvtitle, stli_drvversion);

spin_lock_init(&stli_lock);
spin_lock_init(&brd_lock);

- stli_initbrds();
-
- stli_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
- if (!stli_serial)
- return -ENOMEM;
-
-/*
- * Allocate a temporary write buffer.
- */
stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL);
- if (!stli_txcookbuf)
+ if (!stli_txcookbuf) {
printk(KERN_ERR "STALLION: failed to allocate memory "
"(size=%d)\n", STLI_TXBUFSIZE);
+ retval = -ENOMEM;
+ goto err;
+ }

-/*
- * Set up a character driver for the shared memory region. We need this
- * to down load the slave code image. Also it is a useful debugging tool.
- */
- if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem))
- printk(KERN_ERR "STALLION: failed to register serial memory "
- "device\n");
-
- istallion_class = class_create(THIS_MODULE, "staliomem");
- for (i = 0; i < 4; i++)
- class_device_create(istallion_class, NULL,
- MKDEV(STL_SIOMEMMAJOR, i),
- NULL, "staliomem%d", i);
+ stli_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
+ if (!stli_serial) {
+ retval = -ENOMEM;
+ goto err_free;
+ }

-/*
- * Set up the tty driver structure and register us as a driver.
- */
stli_serial->owner = THIS_MODULE;
stli_serial->driver_name = stli_drvname;
stli_serial->name = stli_serialname;
@@ -4596,58 +4599,75 @@ static int __init istallion_module_init(
stli_serial->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(stli_serial, &stli_ops);

- if (tty_register_driver(stli_serial)) {
- put_tty_driver(stli_serial);
+ retval = tty_register_driver(stli_serial);
+ if (retval) {
printk(KERN_ERR "STALLION: failed to register serial driver\n");
- return -EBUSY;
+ goto err_ttyput;
+ }
+
+ retval = stli_initbrds();
+ if (retval)
+ goto err_ttyunr;
+
+/*
+ * Set up a character driver for the shared memory region. We need this
+ * to down load the slave code image. Also it is a useful debugging tool.
+ */
+ retval = register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem);
+ if (retval) {
+ printk(KERN_ERR "STALLION: failed to register serial memory "
+ "device\n");
+ goto err_deinit;
}
+
+ istallion_class = class_create(THIS_MODULE, "staliomem");
+ for (i = 0; i < 4; i++)
+ class_device_create(istallion_class, NULL,
+ MKDEV(STL_SIOMEMMAJOR, i),
+ NULL, "staliomem%d", i);
+
return 0;
+err_deinit:
+ pci_unregister_driver(&stli_pcidriver);
+ istallion_cleanup_isa();
+err_ttyunr:
+ tty_unregister_driver(stli_serial);
+err_ttyput:
+ put_tty_driver(stli_serial);
+err_free:
+ kfree(stli_txcookbuf);
+err:
+ return retval;
}

/*****************************************************************************/

static void __exit istallion_module_exit(void)
{
- struct stlibrd *brdp;
unsigned int j;
- int i;

printk(KERN_INFO "Unloading %s: version %s\n", stli_drvtitle,
stli_drvversion);

- pci_unregister_driver(&stli_pcidriver);
- /*
- * Free up all allocated resources used by the ports. This includes
- * memory and interrupts.
- */
if (stli_timeron) {
stli_timeron = 0;
del_timer_sync(&stli_timerlist);
}

- i = tty_unregister_driver(stli_serial);
- put_tty_driver(stli_serial);
+ unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
+
for (j = 0; j < 4; j++)
- class_device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, j));
+ class_device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR,
+ j));
class_destroy(istallion_class);
- if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
- printk("STALLION: failed to un-register serial memory device, "
- "errno=%d\n", -i);
-
- kfree(stli_txcookbuf);

- for (j = 0; (j < stli_nrbrds); j++) {
- if ((brdp = stli_brds[j]) == NULL || (brdp->state & BST_PROBED))
- continue;
+ pci_unregister_driver(&stli_pcidriver);
+ istallion_cleanup_isa();

- stli_cleanup_ports(brdp);
+ tty_unregister_driver(stli_serial);
+ put_tty_driver(stli_serial);

- iounmap(brdp->membase);
- if (brdp->iosize > 0)
- release_region(brdp->iobase, brdp->iosize);
- kfree(brdp);
- stli_brds[j] = NULL;
- }
+ kfree(stli_txcookbuf);
}

module_init(istallion_module_init);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/