Commit 0342d35c authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN: Cleanup/fix isdn.o initialization

A small step in cleaning up isdn.o, fixing various bugs on the error paths.
parent a88d5fce
......@@ -2247,13 +2247,15 @@ static void isdn_cleanup_devfs(void)
static int __init isdn_init(void)
{
int i;
int retval;
char tmprev[50];
if (!(dev = (isdn_dev *) vmalloc(sizeof(isdn_dev)))) {
printk(KERN_WARNING "isdn: Could not allocate device-struct.\n");
return -EIO;
dev = vmalloc(sizeof(*dev));
if (!dev) {
retval = -ENOMEM;
goto err;
}
memset((char *) dev, 0, sizeof(isdn_dev));
memset(dev, 0, sizeof(*dev));
init_timer(&dev->timer);
dev->timer.function = isdn_timer_funct;
init_MUTEX(&dev->sem);
......@@ -2266,34 +2268,22 @@ static int __init isdn_init(void)
init_waitqueue_head(&dev->mdm.info[i].open_wait);
init_waitqueue_head(&dev->mdm.info[i].close_wait);
}
if (devfs_register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) {
retval = devfs_register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops);
if (retval) {
printk(KERN_WARNING "isdn: Could not register control devices\n");
vfree(dev);
return -EIO;
goto err_vfree;
}
isdn_init_devfs();
if ((i = isdn_tty_modem_init()) < 0) {
retval = isdn_tty_init();
if (retval < 0) {
printk(KERN_WARNING "isdn: Could not register tty devices\n");
if (i == -3)
tty_unregister_driver(&dev->mdm.cua_modem);
if (i <= -2)
tty_unregister_driver(&dev->mdm.tty_modem);
vfree(dev);
isdn_cleanup_devfs();
devfs_unregister_chrdev(ISDN_MAJOR, "isdn");
return -EIO;
goto err_cleanup_devfs;
}
#ifdef CONFIG_ISDN_PPP
if (isdn_ppp_init() < 0) {
retval = isdn_ppp_init();
if (retval < 0) {
printk(KERN_WARNING "isdn: Could not create PPP-device-structs\n");
tty_unregister_driver(&dev->mdm.tty_modem);
tty_unregister_driver(&dev->mdm.cua_modem);
for (i = 0; i < ISDN_MAX_CHANNELS; i++)
kfree(dev->mdm.info[i].xmit_buf - 4);
isdn_cleanup_devfs();
devfs_unregister_chrdev(ISDN_MAJOR, "isdn");
vfree(dev);
return -EIO;
goto err_tty_modem;
}
#endif /* CONFIG_ISDN_PPP */
......@@ -2317,6 +2307,15 @@ static int __init isdn_init(void)
#endif
isdn_info_update();
return 0;
err_tty_modem:
isdn_tty_exit();
err_cleanup_devfs:
isdn_cleanup_devfs();
err_vfree:
vfree(dev);
err:
return retval;
}
/*
......@@ -2325,46 +2324,24 @@ static int __init isdn_init(void)
static void __exit isdn_exit(void)
{
unsigned long flags;
int i;
#ifdef CONFIG_ISDN_PPP
isdn_ppp_cleanup();
#endif
save_flags(flags);
cli();
if (isdn_net_rmall() < 0) {
printk(KERN_WARNING "isdn: net-device busy, remove cancelled\n");
restore_flags(flags);
return;
}
if (tty_unregister_driver(&dev->mdm.tty_modem)) {
printk(KERN_WARNING "isdn: ttyI-device busy, remove cancelled\n");
restore_flags(flags);
return;
}
if (tty_unregister_driver(&dev->mdm.cua_modem)) {
printk(KERN_WARNING "isdn: cui-device busy, remove cancelled\n");
restore_flags(flags);
return;
}
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
isdn_tty_cleanup_xmit(&dev->mdm.info[i]);
kfree(dev->mdm.info[i].xmit_buf - 4);
#ifdef CONFIG_ISDN_TTY_FAX
kfree(dev->mdm.info[i].fax);
#endif
}
if (devfs_unregister_chrdev(ISDN_MAJOR, "isdn") != 0) {
printk(KERN_WARNING "isdn: controldevice busy, remove cancelled\n");
restore_flags(flags);
} else {
if (isdn_net_rmall() < 0)
BUG();
isdn_tty_exit();
if (devfs_unregister_chrdev(ISDN_MAJOR, "isdn"))
BUG();
isdn_cleanup_devfs();
del_timer(&dev->timer);
restore_flags(flags);
/* call vfree with interrupts enabled, else it will hang */
vfree(dev);
printk(KERN_NOTICE "ISDN-subsystem unloaded\n");
}
}
module_init(isdn_init);
......
......@@ -2015,10 +2015,10 @@ modem_write_profile(atemu * m)
}
int
isdn_tty_modem_init(void)
isdn_tty_init(void)
{
modem *m;
int i;
int i, retval;
modem_info *info;
m = &dev->mdm;
......@@ -2063,13 +2063,15 @@ isdn_tty_modem_init(void)
m->tty_modem.minor_start = 0;
m->cua_modem.subtype = ISDN_SERIAL_TYPE_CALLOUT;
if (tty_register_driver(&m->tty_modem)) {
retval = tty_register_driver(&m->tty_modem);
if (retval) {
printk(KERN_WARNING "isdn_tty: Couldn't register modem-device\n");
return -1;
goto err;
}
if (tty_register_driver(&m->cua_modem)) {
retval = tty_register_driver(&m->cua_modem);
if (retval) {
printk(KERN_WARNING "isdn_tty: Couldn't register modem-callout-device\n");
return -2;
goto err_unregister_tty;
}
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
info = &m->info[i];
......@@ -2106,16 +2108,52 @@ isdn_tty_modem_init(void)
#ifdef CONFIG_ISDN_AUDIO
skb_queue_head_init(&info->dtmf_queue);
#endif
if (!(info->xmit_buf = kmalloc(ISDN_SERIAL_XMIT_MAX + 5, GFP_KERNEL))) {
info->xmit_buf = kmalloc(ISDN_SERIAL_XMIT_MAX + 5, GFP_KERNEL);
if (!info->xmit_buf) {
printk(KERN_ERR "Could not allocate modem xmit-buffer\n");
return -3;
#ifdef CONFIG_ISDN_TTY_FAX
kfree(info->fax);
#endif
goto err_unregister_cua;
}
/* Make room for T.70 header */
info->xmit_buf += 4;
}
return 0;
err_unregister_cua:
for (i--; i >= 0; i--) {
info = &m->info[i];
#ifdef CONFIG_ISDN_TTY_FAX
kfree(info->fax);
#endif
kfree(info->xmit_buf - 4);
}
tty_unregister_driver(&dev->mdm.cua_modem);
err_unregister_tty:
tty_unregister_driver(&dev->mdm.tty_modem);
err:
return retval;
}
void
isdn_tty_exit(void)
{
modem *m = &dev->mdm;
modem_info *info;
int i;
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
info = &m->info[i];
isdn_tty_cleanup_xmit(info);
#ifdef CONFIG_ISDN_TTY_FAX
kfree(info->fax);
#endif
kfree(info->xmit_buf - 4);
}
tty_unregister_driver(&dev->mdm.cua_modem);
tty_unregister_driver(&dev->mdm.tty_modem);
}
/*
* isdn_tty_match_icall(char *MSN, atemu *tty_emulator, int dev_idx)
......
......@@ -105,7 +105,7 @@ extern void isdn_tty_modem_escape(void);
extern void isdn_tty_modem_ring(void);
extern void isdn_tty_carrier_timeout(void);
extern void isdn_tty_modem_xmit(void);
extern int isdn_tty_modem_init(void);
extern int isdn_tty_init(void);
extern void isdn_tty_readmodem(void);
extern int isdn_tty_find_icall(int, int, setup_parm *);
extern void isdn_tty_cleanup_xmit(modem_info *);
......@@ -119,3 +119,6 @@ extern int isdn_tty_cmd_PLUSF_FAX(char **, modem_info *);
extern int isdn_tty_fax_command(modem_info *, isdn_ctrl *);
extern void isdn_tty_fax_bitorder(modem_info *, struct sk_buff *);
#endif
extern int isdn_tty_init(void);
extern void isdn_tty_exit(void);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment