Skip to content

Commit

Permalink
[PATCH] Char: istallion, change init sequence
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jiri Slaby authored and Linus Torvalds committed Dec 8, 2006
1 parent f1cc54f commit f2362c9
Showing 1 changed file with 75 additions and 55 deletions.
130 changes: 75 additions & 55 deletions drivers/char/istallion.c
Original file line number Diff line number Diff line change
Expand Up @@ -4545,46 +4545,49 @@ static const struct tty_operations stli_ops = {
* 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;
Expand All @@ -4596,58 +4599,75 @@ static int __init istallion_module_init(void)
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);
Expand Down

0 comments on commit f2362c9

Please sign in to comment.