Skip to content

Commit

Permalink
TTY: call tty_port_destroy in the rest of drivers
Browse files Browse the repository at this point in the history
After commit "TTY: move tty buffers to tty_port", the tty buffers are
not freed in some drivers. This is because tty_port_destructor is not
called whenever a tty_port is freed. This was an assumption I counted
with but was unfortunately untrue. So fix the drivers to fulfil this
assumption.

To be sure, the TTY buffers (and later some stuff) are gone along with
the tty_port, we have to call tty_port_destroy at tear-down places.
This is mostly where the structure containing a tty_port is freed.
This patch does exactly that -- put tty_port_destroy at those places.

Signed-off-by: Jiri Slaby <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
Jiri Slaby authored and gregkh committed Nov 16, 2012
1 parent d0f5914 commit 191c5f1
Show file tree
Hide file tree
Showing 41 changed files with 139 additions and 40 deletions.
5 changes: 4 additions & 1 deletion arch/alpha/kernel/srmcons.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,6 @@ static const struct tty_operations srmcons_ops = {
static int __init
srmcons_init(void)
{
tty_port_init(&srmcons_singleton.port);
setup_timer(&srmcons_singleton.timer, srmcons_receive_chars,
(unsigned long)&srmcons_singleton);
if (srm_is_registered_console) {
Expand All @@ -215,6 +214,9 @@ srmcons_init(void)
driver = alloc_tty_driver(MAX_SRM_CONSOLE_DEVICES);
if (!driver)
return -ENOMEM;

tty_port_init(&srmcons_singleton.port);

driver->driver_name = "srm";
driver->name = "srm";
driver->major = 0; /* dynamic */
Expand All @@ -227,6 +229,7 @@ srmcons_init(void)
err = tty_register_driver(driver);
if (err) {
put_tty_driver(driver);
tty_port_destroy(&srmcons_singleton.port);
return err;
}
srmcons_driver = driver;
Expand Down
1 change: 1 addition & 0 deletions arch/ia64/hp/sim/simserial.c
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,7 @@ static int __init simrs_init(void)
return 0;
err_free_tty:
put_tty_driver(hp_simserial_driver);
tty_port_destroy(&state->port);
return retval;
}

Expand Down
6 changes: 4 additions & 2 deletions arch/m68k/emu/nfcon.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,6 @@ static int __init nfcon_init(void)
{
int res;

tty_port_init(&nfcon_tty_port);

stderr_id = nf_get_id("NF_STDERR");
if (!stderr_id)
return -ENODEV;
Expand All @@ -130,6 +128,8 @@ static int __init nfcon_init(void)
if (!nfcon_tty_driver)
return -ENOMEM;

tty_port_init(&nfcon_tty_port);

nfcon_tty_driver->driver_name = "nfcon";
nfcon_tty_driver->name = "nfcon";
nfcon_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;
Expand All @@ -143,6 +143,7 @@ static int __init nfcon_init(void)
if (res) {
pr_err("failed to register nfcon tty driver\n");
put_tty_driver(nfcon_tty_driver);
tty_port_destroy(&nfcon_tty_port);
return res;
}

Expand All @@ -157,6 +158,7 @@ static void __exit nfcon_exit(void)
unregister_console(&nf_console);
tty_unregister_driver(nfcon_tty_driver);
put_tty_driver(nfcon_tty_driver);
tty_port_destroy(&nfcon_tty_port);
}

module_init(nfcon_init);
Expand Down
5 changes: 3 additions & 2 deletions arch/parisc/kernel/pdc_cons.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,13 @@ static int __init pdc_console_tty_driver_init(void)
printk(KERN_INFO "The PDC console driver is still registered, removing CON_BOOT flag\n");
pdc_cons.flags &= ~CON_BOOT;

tty_port_init(&tty_port);

pdc_console_tty_driver = alloc_tty_driver(1);

if (!pdc_console_tty_driver)
return -ENOMEM;

tty_port_init(&tty_port);

pdc_console_tty_driver->driver_name = "pdc_cons";
pdc_console_tty_driver->name = "ttyB";
pdc_console_tty_driver->major = MUX_MAJOR;
Expand All @@ -207,6 +207,7 @@ static int __init pdc_console_tty_driver_init(void)
err = tty_register_driver(pdc_console_tty_driver);
if (err) {
printk(KERN_ERR "Unable to register the PDC console TTY driver\n");
tty_port_destroy(&tty_port);
return err;
}

Expand Down
2 changes: 2 additions & 0 deletions arch/um/drivers/line.c
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,8 @@ int register_lines(struct line_driver *line_driver,
printk(KERN_ERR "register_lines : can't register %s driver\n",
line_driver->name);
put_tty_driver(driver);
for (i = 0; i < nlines; i++)
tty_port_destroy(&lines[i].port);
return err;
}

Expand Down
1 change: 1 addition & 0 deletions arch/xtensa/platforms/iss/console.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ static __exit void rs_exit(void)
printk("ISS_SERIAL: failed to unregister serial driver (%d)\n",
error);
put_tty_driver(serial_driver);
tty_port_destroy(&serial_port);
}


Expand Down
5 changes: 4 additions & 1 deletion drivers/char/pcmcia/synclink_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -549,8 +549,10 @@ static int mgslpc_probe(struct pcmcia_device *link)
/* Initialize the struct pcmcia_device structure */

ret = mgslpc_config(link);
if (ret)
if (ret) {
tty_port_destroy(&info->port);
return ret;
}

mgslpc_add_device(info);

Expand Down Expand Up @@ -2757,6 +2759,7 @@ static void mgslpc_remove_device(MGSLPC_INFO *remove_info)
hdlcdev_exit(info);
#endif
release_resources(info);
tty_port_destroy(&info->port);
kfree(info);
mgslpc_device_count--;
return;
Expand Down
4 changes: 3 additions & 1 deletion drivers/char/ttyprintk.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,6 @@ static int __init ttyprintk_init(void)
{
int ret = -ENOMEM;

tty_port_init(&tpk_port.port);
tpk_port.port.ops = &null_ops;
mutex_init(&tpk_port.port_write_mutex);

Expand All @@ -190,6 +189,8 @@ static int __init ttyprintk_init(void)
if (IS_ERR(ttyprintk_driver))
return PTR_ERR(ttyprintk_driver);

tty_port_init(&tpk_port.port);

ttyprintk_driver->driver_name = "ttyprintk";
ttyprintk_driver->name = "ttyprintk";
ttyprintk_driver->major = TTYAUX_MAJOR;
Expand All @@ -211,6 +212,7 @@ static int __init ttyprintk_init(void)
error:
tty_unregister_driver(ttyprintk_driver);
put_tty_driver(ttyprintk_driver);
tty_port_destroy(&tpk_port.port);
ttyprintk_driver = NULL;
return ret;
}
Expand Down
10 changes: 6 additions & 4 deletions drivers/isdn/gigaset/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,7 @@ f_bcs: gig_dbg(DEBUG_INIT, "freeing bcs[]");
kfree(cs->bcs);
f_cs: gig_dbg(DEBUG_INIT, "freeing cs");
mutex_unlock(&cs->mutex);
tty_port_destroy(&cs->port);
free_cs(cs);
}
EXPORT_SYMBOL_GPL(gigaset_freecs);
Expand Down Expand Up @@ -751,14 +752,14 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
gig_dbg(DEBUG_INIT, "setting up iif");
if (gigaset_isdn_regdev(cs, modulename) < 0) {
pr_err("error registering ISDN device\n");
goto error;
goto error_port;
}

make_valid(cs, VALID_ID);
++cs->cs_init;
gig_dbg(DEBUG_INIT, "setting up hw");
if (cs->ops->initcshw(cs) < 0)
goto error;
goto error_port;

++cs->cs_init;

Expand All @@ -773,7 +774,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
gig_dbg(DEBUG_INIT, "setting up bcs[%d]", i);
if (gigaset_initbcs(cs->bcs + i, cs, i) < 0) {
pr_err("could not allocate channel %d data\n", i);
goto error;
goto error_port;
}
}

Expand All @@ -786,7 +787,8 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,

gig_dbg(DEBUG_INIT, "cs initialized");
return cs;

error_port:
tty_port_destroy(&cs->port);
error:
gig_dbg(DEBUG_INIT, "failed");
gigaset_freecs(cs);
Expand Down
4 changes: 4 additions & 0 deletions drivers/isdn/i4l/isdn_tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -1849,6 +1849,8 @@ isdn_tty_modem_init(void)
kfree(info->fax);
#endif
kfree(info->port.xmit_buf - 4);
info->port.xmit_buf = NULL;
tty_port_destroy(&info->port);
}
tty_unregister_driver(m->tty_modem);
err:
Expand All @@ -1870,6 +1872,8 @@ isdn_tty_exit(void)
kfree(info->fax);
#endif
kfree(info->port.xmit_buf - 4);
info->port.xmit_buf = NULL;
tty_port_destroy(&info->port);
}
tty_unregister_driver(dev->mdm.tty_modem);
put_tty_driver(dev->mdm.tty_modem);
Expand Down
7 changes: 5 additions & 2 deletions drivers/misc/pti.c
Original file line number Diff line number Diff line change
Expand Up @@ -882,11 +882,14 @@ static int __devinit pti_pci_probe(struct pci_dev *pdev,
static void __devexit pti_pci_remove(struct pci_dev *pdev)
{
struct pti_dev *drv_data = pci_get_drvdata(pdev);
unsigned int a;

unregister_console(&pti_console);

tty_unregister_device(pti_tty_driver, 0);
tty_unregister_device(pti_tty_driver, 1);
for (a = 0; a < PTITTY_MINOR_NUM; a++) {
tty_unregister_device(pti_tty_driver, a);
tty_port_destroy(&drv_data->port[a]);
}

iounmap(drv_data->pti_ioaddr);
pci_set_drvdata(pdev, NULL);
Expand Down
5 changes: 3 additions & 2 deletions drivers/net/usb/hso.c
Original file line number Diff line number Diff line change
Expand Up @@ -2274,6 +2274,7 @@ static void hso_serial_common_free(struct hso_serial *serial)
/* unlink and free TX URB */
usb_free_urb(serial->tx_urb);
kfree(serial->tx_data);
tty_port_destroy(&serial->port);
}

static int hso_serial_common_create(struct hso_serial *serial, int num_urbs,
Expand All @@ -2283,12 +2284,12 @@ static int hso_serial_common_create(struct hso_serial *serial, int num_urbs,
int minor;
int i;

tty_port_init(&serial->port);

minor = get_free_serial_index();
if (minor < 0)
goto exit;

tty_port_init(&serial->port);

/* register our minor number */
serial->parent->dev = tty_port_register_device(&serial->port, tty_drv,
minor, &serial->parent->interface->dev);
Expand Down
1 change: 1 addition & 0 deletions drivers/s390/char/con3215.c
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,7 @@ static void raw3215_free_info(struct raw3215_info *raw)
{
kfree(raw->inbuf);
kfree(raw->buffer);
tty_port_destroy(&raw->port);
kfree(raw);
}

Expand Down
4 changes: 3 additions & 1 deletion drivers/s390/char/sclp_tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -547,14 +547,15 @@ sclp_tty_init(void)
sclp_tty_tolower = 1;
}
sclp_tty_chars_count = 0;
tty_port_init(&sclp_port);

rc = sclp_register(&sclp_input_event);
if (rc) {
put_tty_driver(driver);
return rc;
}

tty_port_init(&sclp_port);

driver->driver_name = "sclp_line";
driver->name = "sclp_line";
driver->major = TTY_MAJOR;
Expand All @@ -571,6 +572,7 @@ sclp_tty_init(void)
rc = tty_register_driver(driver);
if (rc) {
put_tty_driver(driver);
tty_port_destroy(&sclp_port);
return rc;
}
sclp_tty_driver = driver;
Expand Down
2 changes: 2 additions & 0 deletions drivers/s390/char/sclp_vt220.c
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,7 @@ static void __init __sclp_vt220_cleanup(void)
return;
sclp_unregister(&sclp_vt220_register);
__sclp_vt220_free_pages();
tty_port_destroy(&sclp_vt220_port);
}

/* Allocate buffer pages and register with sclp core. Controlled by init
Expand Down Expand Up @@ -650,6 +651,7 @@ static int __init __sclp_vt220_init(int num_pages)
if (rc) {
__sclp_vt220_free_pages();
sclp_vt220_init_count--;
tty_port_destroy(&sclp_vt220_port);
}
return rc;
}
Expand Down
2 changes: 2 additions & 0 deletions drivers/s390/char/tty3270.c
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,7 @@ tty3270_alloc_view(void)
while (pages--)
free_pages((unsigned long) tp->freemem_pages[pages], 0);
kfree(tp->freemem_pages);
tty_port_destroy(&tp->port);
out_tp:
kfree(tp);
out_err:
Expand All @@ -744,6 +745,7 @@ tty3270_free_view(struct tty3270 *tp)
for (pages = 0; pages < TTY3270_STRING_PAGES; pages++)
free_pages((unsigned long) tp->freemem_pages[pages], 0);
kfree(tp->freemem_pages);
tty_port_destroy(&tp->port);
kfree(tp);
}

Expand Down
5 changes: 4 additions & 1 deletion drivers/staging/ccg/u_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -1140,8 +1140,10 @@ int gserial_setup(struct usb_gadget *g, unsigned count)

return status;
fail:
while (count--)
while (count--) {
tty_port_destroy(&ports[count].port->port);
kfree(ports[count].port);
}
put_tty_driver(gs_tty_driver);
gs_tty_driver = NULL;
return status;
Expand Down Expand Up @@ -1195,6 +1197,7 @@ void gserial_cleanup(void)

WARN_ON(port->port_usb != NULL);

tty_port_destroy(&port->port);
kfree(port);
}
n_ports = 0;
Expand Down
2 changes: 2 additions & 0 deletions drivers/staging/dgrp/dgrp_specproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,8 @@ static int dgrp_add_id(long id)

return 0;

/* FIXME this guy should free the tty driver stored in nd and destroy
* all channel ports */
error_out:
kfree(nd);
return ret;
Expand Down
4 changes: 3 additions & 1 deletion drivers/staging/dgrp/dgrp_tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -3119,6 +3119,7 @@ static void dgrp_tty_hangup(struct tty_struct *tty)
void
dgrp_tty_uninit(struct nd_struct *nd)
{
unsigned int i;
char id[3];

ID_TO_CHAR(nd->nd_ID, id);
Expand Down Expand Up @@ -3152,6 +3153,8 @@ dgrp_tty_uninit(struct nd_struct *nd)
put_tty_driver(nd->nd_xprint_ttdriver);
nd->nd_ttdriver_flags &= ~XPRINT_TTDRV_REG;
}
for (i = 0; i < CHAN_MAX; i++)
tty_port_destroy(&nd->nd_chan[i].port);
}


Expand Down Expand Up @@ -3335,7 +3338,6 @@ dgrp_tty_init(struct nd_struct *nd)
init_waitqueue_head(&(ch->ch_pun.un_open_wait));
init_waitqueue_head(&(ch->ch_pun.un_close_wait));
tty_port_init(&ch->port);
tty_port_init(&ch->port);
}
return 0;
}
2 changes: 2 additions & 0 deletions drivers/staging/ipack/devices/ipoctal.c
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
tty_dev = tty_port_register_device(&channel->tty_port, tty, i, NULL);
if (IS_ERR(tty_dev)) {
dev_err(&ipoctal->dev->dev, "Failed to register tty device.\n");
tty_port_destroy(&channel->tty_port);
continue;
}
dev_set_drvdata(tty_dev, channel);
Expand Down Expand Up @@ -741,6 +742,7 @@ static void __ipoctal_remove(struct ipoctal *ipoctal)
struct ipoctal_channel *channel = &ipoctal->channel[i];
tty_unregister_device(ipoctal->tty_drv, i);
tty_port_free_xmit_buf(&channel->tty_port);
tty_port_destroy(&channel->tty_port);
}

tty_unregister_driver(ipoctal->tty_drv);
Expand Down
Loading

0 comments on commit 191c5f1

Please sign in to comment.