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) ...@@ -2247,13 +2247,15 @@ static void isdn_cleanup_devfs(void)
static int __init isdn_init(void) static int __init isdn_init(void)
{ {
int i; int i;
int retval;
char tmprev[50]; char tmprev[50];
if (!(dev = (isdn_dev *) vmalloc(sizeof(isdn_dev)))) { dev = vmalloc(sizeof(*dev));
printk(KERN_WARNING "isdn: Could not allocate device-struct.\n"); if (!dev) {
return -EIO; retval = -ENOMEM;
goto err;
} }
memset((char *) dev, 0, sizeof(isdn_dev)); memset(dev, 0, sizeof(*dev));
init_timer(&dev->timer); init_timer(&dev->timer);
dev->timer.function = isdn_timer_funct; dev->timer.function = isdn_timer_funct;
init_MUTEX(&dev->sem); init_MUTEX(&dev->sem);
...@@ -2266,34 +2268,22 @@ static int __init isdn_init(void) ...@@ -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].open_wait);
init_waitqueue_head(&dev->mdm.info[i].close_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"); printk(KERN_WARNING "isdn: Could not register control devices\n");
vfree(dev); goto err_vfree;
return -EIO;
} }
isdn_init_devfs(); 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"); printk(KERN_WARNING "isdn: Could not register tty devices\n");
if (i == -3) goto err_cleanup_devfs;
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;
} }
#ifdef CONFIG_ISDN_PPP #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"); printk(KERN_WARNING "isdn: Could not create PPP-device-structs\n");
tty_unregister_driver(&dev->mdm.tty_modem); goto err_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;
} }
#endif /* CONFIG_ISDN_PPP */ #endif /* CONFIG_ISDN_PPP */
...@@ -2317,6 +2307,15 @@ static int __init isdn_init(void) ...@@ -2317,6 +2307,15 @@ static int __init isdn_init(void)
#endif #endif
isdn_info_update(); isdn_info_update();
return 0; 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) ...@@ -2325,46 +2324,24 @@ static int __init isdn_init(void)
static void __exit isdn_exit(void) static void __exit isdn_exit(void)
{ {
unsigned long flags; unsigned long flags;
int i;
#ifdef CONFIG_ISDN_PPP #ifdef CONFIG_ISDN_PPP
isdn_ppp_cleanup(); isdn_ppp_cleanup();
#endif #endif
save_flags(flags); save_flags(flags);
cli(); cli();
if (isdn_net_rmall() < 0) { if (isdn_net_rmall() < 0)
printk(KERN_WARNING "isdn: net-device busy, remove cancelled\n"); BUG();
restore_flags(flags);
return; isdn_tty_exit();
} if (devfs_unregister_chrdev(ISDN_MAJOR, "isdn"))
if (tty_unregister_driver(&dev->mdm.tty_modem)) { BUG();
printk(KERN_WARNING "isdn: ttyI-device busy, remove cancelled\n");
restore_flags(flags); isdn_cleanup_devfs();
return; del_timer(&dev->timer);
} restore_flags(flags);
if (tty_unregister_driver(&dev->mdm.cua_modem)) { /* call vfree with interrupts enabled, else it will hang */
printk(KERN_WARNING "isdn: cui-device busy, remove cancelled\n"); vfree(dev);
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 {
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); module_init(isdn_init);
......
...@@ -2015,10 +2015,10 @@ modem_write_profile(atemu * m) ...@@ -2015,10 +2015,10 @@ modem_write_profile(atemu * m)
} }
int int
isdn_tty_modem_init(void) isdn_tty_init(void)
{ {
modem *m; modem *m;
int i; int i, retval;
modem_info *info; modem_info *info;
m = &dev->mdm; m = &dev->mdm;
...@@ -2063,13 +2063,15 @@ isdn_tty_modem_init(void) ...@@ -2063,13 +2063,15 @@ isdn_tty_modem_init(void)
m->tty_modem.minor_start = 0; m->tty_modem.minor_start = 0;
m->cua_modem.subtype = ISDN_SERIAL_TYPE_CALLOUT; 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"); 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"); 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++) { for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
info = &m->info[i]; info = &m->info[i];
...@@ -2106,16 +2108,52 @@ isdn_tty_modem_init(void) ...@@ -2106,16 +2108,52 @@ isdn_tty_modem_init(void)
#ifdef CONFIG_ISDN_AUDIO #ifdef CONFIG_ISDN_AUDIO
skb_queue_head_init(&info->dtmf_queue); skb_queue_head_init(&info->dtmf_queue);
#endif #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"); 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 */ /* Make room for T.70 header */
info->xmit_buf += 4; info->xmit_buf += 4;
} }
return 0; 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) * isdn_tty_match_icall(char *MSN, atemu *tty_emulator, int dev_idx)
......
...@@ -105,7 +105,7 @@ extern void isdn_tty_modem_escape(void); ...@@ -105,7 +105,7 @@ extern void isdn_tty_modem_escape(void);
extern void isdn_tty_modem_ring(void); extern void isdn_tty_modem_ring(void);
extern void isdn_tty_carrier_timeout(void); extern void isdn_tty_carrier_timeout(void);
extern void isdn_tty_modem_xmit(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 void isdn_tty_readmodem(void);
extern int isdn_tty_find_icall(int, int, setup_parm *); extern int isdn_tty_find_icall(int, int, setup_parm *);
extern void isdn_tty_cleanup_xmit(modem_info *); extern void isdn_tty_cleanup_xmit(modem_info *);
...@@ -119,3 +119,6 @@ extern int isdn_tty_cmd_PLUSF_FAX(char **, 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 int isdn_tty_fax_command(modem_info *, isdn_ctrl *);
extern void isdn_tty_fax_bitorder(modem_info *, struct sk_buff *); extern void isdn_tty_fax_bitorder(modem_info *, struct sk_buff *);
#endif #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