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) {
                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 */
                err = tty_register_driver(driver);
                if (err) {
                        put_tty_driver(driver);
+                       tty_port_destroy(&srmcons_singleton.port);
                        return err;
                }
                srmcons_driver = driver;
 
        return 0;
 err_free_tty:
        put_tty_driver(hp_simserial_driver);
+       tty_port_destroy(&state->port);
        return retval;
 }
 
 
 {
        int res;
 
-       tty_port_init(&nfcon_tty_port);
-
        stderr_id = nf_get_id("NF_STDERR");
        if (!stderr_id)
                return -ENODEV;
        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;
        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;
        }
 
        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);
 
        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;
        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;
        }
 
 
                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;
        }
 
 
                printk("ISS_SERIAL: failed to unregister serial driver (%d)\n",
                       error);
        put_tty_driver(serial_driver);
+       tty_port_destroy(&serial_port);
 }
 
 
 
     /* 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);
 
                        hdlcdev_exit(info);
 #endif
                        release_resources(info);
+                       tty_port_destroy(&info->port);
                        kfree(info);
                        mgslpc_device_count--;
                        return;
 
 {
        int ret = -ENOMEM;
 
-       tty_port_init(&tpk_port.port);
        tpk_port.port.ops = &null_ops;
        mutex_init(&tpk_port.port_write_mutex);
 
        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;
 error:
        tty_unregister_driver(ttyprintk_driver);
        put_tty_driver(ttyprintk_driver);
+       tty_port_destroy(&tpk_port.port);
        ttyprintk_driver = NULL;
        return ret;
 }
 
        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);
        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;
 
                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;
                }
        }
 
 
        gig_dbg(DEBUG_INIT, "cs initialized");
        return cs;
-
+error_port:
+       tty_port_destroy(&cs->port);
 error:
        gig_dbg(DEBUG_INIT, "failed");
        gigaset_freecs(cs);
 
                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:
                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);
 
 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);
 
        /* 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,
        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);
 
 {
        kfree(raw->inbuf);
        kfree(raw->buffer);
+       tty_port_destroy(&raw->port);
        kfree(raw);
 }
 
 
                sclp_tty_tolower = 1;
        }
        sclp_tty_chars_count = 0;
-       tty_port_init(&sclp_port);
 
        rc = sclp_register(&sclp_input_event);
        if (rc) {
                return rc;
        }
 
+       tty_port_init(&sclp_port);
+
        driver->driver_name = "sclp_line";
        driver->name = "sclp_line";
        driver->major = TTY_MAJOR;
        rc = tty_register_driver(driver);
        if (rc) {
                put_tty_driver(driver);
+               tty_port_destroy(&sclp_port);
                return rc;
        }
        sclp_tty_driver = driver;
 
                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
        if (rc) {
                __sclp_vt220_free_pages();
                sclp_vt220_init_count--;
+               tty_port_destroy(&sclp_vt220_port);
        }
        return rc;
 }
 
        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:
        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);
 }
 
 
 
        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;
 
                WARN_ON(port->port_usb != NULL);
 
+               tty_port_destroy(&port->port);
                kfree(port);
        }
        n_ports = 0;
 
 
        return 0;
 
+       /* FIXME this guy should free the tty driver stored in nd and destroy
+        * all channel ports */
 error_out:
        kfree(nd);
        return ret;
 
 void
 dgrp_tty_uninit(struct nd_struct *nd)
 {
+       unsigned int i;
        char id[3];
 
        ID_TO_CHAR(nd->nd_ID, id);
                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);
 }
 
 
                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;
 }
 
                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);
                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);
 
 fail_unregister:
        tty_unregister_driver(serial_driver);
 fail_put_tty_driver:
+       tty_port_destroy(&state->tport);
        put_tty_driver(serial_driver);
        return error;
 }
                printk("SERIAL: failed to unregister serial driver (%d)\n",
                       error);
        put_tty_driver(serial_driver);
+       tty_port_destroy(&state->tport);
 
        free_irq(IRQ_AMIGA_TBE, state);
        free_irq(IRQ_AMIGA_RBF, state);
 
 {
        int ret;
 
-       tty_port_init(&port);
-
        bfin_jc_kthread = kthread_create(bfin_jc_emudat_manager, NULL, DRV_NAME);
        if (IS_ERR(bfin_jc_kthread))
                return PTR_ERR(bfin_jc_kthread);
        if (!bfin_jc_driver)
                goto err_driver;
 
+       tty_port_init(&port);
+
        bfin_jc_driver->driver_name  = DRV_NAME;
        bfin_jc_driver->name         = DEV_NAME;
        bfin_jc_driver->type         = TTY_DRIVER_TYPE_SERIAL;
        return 0;
 
  err:
+       tty_port_destroy(&port);
        put_tty_driver(bfin_jc_driver);
  err_driver:
        kfree(bfin_jc_write_buf.buf);
        kfree(bfin_jc_write_buf.buf);
        tty_unregister_driver(bfin_jc_driver);
        put_tty_driver(bfin_jc_driver);
+       tty_port_destroy(&port);
 }
 module_exit(bfin_jc_exit);
 
 
 static void __devexit cy_pci_remove(struct pci_dev *pdev)
 {
        struct cyclades_card *cinfo = pci_get_drvdata(pdev);
-       unsigned int i;
+       unsigned int i, channel;
 
        /* non-Z with old PLX */
        if (!cy_is_Z(cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) ==
        pci_release_regions(pdev);
 
        cinfo->base_addr = NULL;
-       for (i = cinfo->first_line; i < cinfo->first_line +
-                       cinfo->nports; i++)
+       for (channel = 0, i = cinfo->first_line; i < cinfo->first_line +
+                       cinfo->nports; i++, channel++) {
                tty_unregister_device(cy_serial_driver, i);
+               tty_port_destroy(&cinfo->ports[channel].port);
+       }
        cinfo->nports = 0;
        kfree(cinfo->ports);
 }
 
        return 0;
 
 error:
+       tty_port_destroy(&bc->port);
        irq_dispose_mapping(bc->tx_irq);
        irq_dispose_mapping(bc->rx_irq);
 
 
        tty_unregister_device(ehv_bc_driver, bc - bcs);
 
+       tty_port_destroy(&bc->port);
        irq_dispose_mapping(bc->tx_irq);
        irq_dispose_mapping(bc->rx_irq);
 
 
                if (hp->virq == 0) {
                        printk(KERN_ERR "%s: couldn't create irq mapping for 0x%x\n",
                                __func__, irq[0]);
+                       tty_port_destroy(&hp->port);
                        continue;
                }
 
 
                        ipwireless_disassociate_network_ttys(network,
                                                             ttyj->channel_idx);
                        tty_unregister_device(ipw_tty_driver, j);
+                       tty_port_destroy(&ttyj->port);
                        ttys[j] = NULL;
                        mutex_unlock(&ttyj->ipw_tty_mutex);
                        kfree(ttyj);
 
 
        return 0;
 err_free:
+       for (i = 0; i < MAX_PORTS_PER_BOARD; i++)
+               tty_port_destroy(&brd->ports[i].port);
        kfree(brd->ports);
 err:
        return ret;
                                tty_kref_put(tty);
                        }
                }
+       for (a = 0; a < MAX_PORTS_PER_BOARD; a++)
+               tty_port_destroy(&brd->ports[a].port);
        while (1) {
                opened = 0;
                for (a = 0; a < brd->numPorts; a++)
 
 
        retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser",
                        brd);
-       if (retval)
+       if (retval) {
+               for (i = 0; i < brd->info->nports; i++)
+                       tty_port_destroy(&brd->ports[i].port);
                printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may "
                        "conflict with another device.\n",
                        brd->info->name, brd->irq);
+       }
 
        return retval;
 }
 
+static void mxser_board_remove(struct mxser_board *brd)
+{
+       unsigned int i;
+
+       for (i = 0; i < brd->info->nports; i++) {
+               tty_unregister_device(mxvar_sdriver, brd->idx + i);
+               tty_port_destroy(&brd->ports[i].port);
+       }
+}
+
 static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd)
 {
        int id, i, bits, ret;
 {
 #ifdef CONFIG_PCI
        struct mxser_board *brd = pci_get_drvdata(pdev);
-       unsigned int i;
 
-       for (i = 0; i < brd->info->nports; i++)
-               tty_unregister_device(mxvar_sdriver, brd->idx + i);
+       mxser_board_remove(brd);
 
        free_irq(pdev->irq, brd);
        pci_release_region(pdev, 2);
 
 static void __exit mxser_module_exit(void)
 {
-       unsigned int i, j;
+       unsigned int i;
 
        pci_unregister_driver(&mxser_driver);
 
        for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */
                if (mxser_boards[i].info != NULL)
-                       for (j = 0; j < mxser_boards[i].info->nports; j++)
-                               tty_unregister_device(mxvar_sdriver,
-                                               mxser_boards[i].idx + j);
+                       mxser_board_remove(&mxser_boards[i]);
        tty_unregister_driver(mxvar_sdriver);
        put_tty_driver(mxvar_sdriver);
 
 
                if (IS_ERR(tty_dev)) {
                        ret = PTR_ERR(tty_dev);
                        dev_err(&pdev->dev, "Could not allocate tty?\n");
+                       tty_port_destroy(&port->port);
                        goto err_free_tty;
                }
        }
        return 0;
 
 err_free_tty:
-       for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i)
-               tty_unregister_device(ntty_driver, i);
+       for (i = 0; i < MAX_PORT; ++i) {
+               tty_unregister_device(ntty_driver, dc->index_start + i);
+               tty_port_destroy(&dc->port[i].port);
+       }
 err_free_kfifo:
        for (i = 0; i < MAX_PORT; i++)
                kfifo_free(&dc->port[i].fifo_ul);
           complete off a hangup method ? */
        while (dc->open_ttys)
                msleep(1);
-       for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i)
-               tty_unregister_device(ntty_driver, i);
+       for (i = 0; i < MAX_PORT; ++i) {
+               tty_unregister_device(ntty_driver, dc->index_start + i);
+               tty_port_destroy(&dc->port[i].port);
+       }
 }
 
 /* Deallocate memory for one device */
 
        if (sInitChan(ctlp, &info->channel, aiop, chan) == 0) {
                printk(KERN_ERR "RocketPort sInitChan(%d, %d, %d) failed!\n",
                                board, aiop, chan);
+               tty_port_destroy(&info->port);
                kfree(info);
                return;
        }
        for (i = 0; i < MAX_RP_PORTS; i++)
                if (rp_table[i]) {
                        tty_unregister_device(rocket_driver, i);
+                       tty_port_destroy(&rp_table[i]->port);
                        kfree(rp_table[i]);
                }
 
 
 
        if (tty_register_driver(serial_driver)) {
                put_tty_driver(serial_driver);
+               for (i = 0; i < NR_PORTS; i++)
+                       tty_port_destroy(&m68k_soft[i].tport);
                printk(KERN_ERR "Couldn't register serial driver\n");
                return -ENOMEM;
        }
 
 {
        if (ifx_dev->tty_dev)
                tty_unregister_device(tty_drv, ifx_dev->minor);
+       tty_port_destroy(&ifx_dev->tty_port);
        kfifo_free(&ifx_dev->tx_fifo);
 }
 
                dev_dbg(&ifx_dev->spi_dev->dev,
                        "%s: registering tty device failed", __func__);
                ret = PTR_ERR(ifx_dev->tty_dev);
-               goto error_ret;
+               goto error_port;
        }
        return 0;
 
+error_port:
+       tty_port_destroy(pport);
 error_ret:
        ifx_spi_free_port(ifx_dev);
        return ret;
 
        }
        return 0;
 err:
+       tty_port_destroy(&priv->port);
        kfree(priv);
        return ret;
 }
        struct kgdb_nmi_tty_priv *priv = tty->driver_data;
 
        tty->driver_data = NULL;
+       tty_port_destroy(&priv->port);
        kfree(priv);
 }
 
 
        if (retval >= 0)
                return retval;
 
+       for (i = 0; i < drv->nr; i++)
+               tty_port_destroy(&drv->state[i].port);
        put_tty_driver(normal);
 out_kfree:
        kfree(drv->state);
 void uart_unregister_driver(struct uart_driver *drv)
 {
        struct tty_driver *p = drv->tty_driver;
+       unsigned int i;
+
        tty_unregister_driver(p);
        put_tty_driver(p);
+       for (i = 0; i < drv->nr; i++)
+               tty_port_destroy(&drv->state[i].port);
        kfree(drv->state);
        drv->state = NULL;
        drv->tty_driver = NULL;
 
                mgsl_release_resources(info);
                tmp = info;
                info = info->next_device;
+               tty_port_destroy(&tmp->port);
                kfree(tmp);
        }
        
 
        for (i=0; i < port_count; ++i) {
                port_array[i] = alloc_dev(adapter_num, i, pdev);
                if (port_array[i] == NULL) {
-                       for (--i; i >= 0; --i)
+                       for (--i; i >= 0; --i) {
+                               tty_port_destroy(&port_array[i]->port);
                                kfree(port_array[i]);
+                       }
                        return;
                }
        }
                        release_resources(info);
                tmp = info;
                info = info->next_device;
+               tty_port_destroy(&tmp->port);
                kfree(tmp);
        }
 
 
        for ( port = 0; port < SCA_MAX_PORTS; ++port ) {
                port_array[port] = alloc_dev(adapter_num,port,pdev);
                if( port_array[port] == NULL ) {
-                       for ( --port; port >= 0; --port )
+                       for (--port; port >= 0; --port) {
+                               tty_port_destroy(&port_array[port]->port);
                                kfree(port_array[port]);
+                       }
                        return;
                }
        }
                }
                tmp = info;
                info = info->next_device;
+               tty_port_destroy(&tmp->port);
                kfree(tmp);
        }
 
 
                con_set_default_unimap(vc);
            vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
            if (!vc->vc_screenbuf) {
+               tty_port_destroy(&vc->port);
                kfree(vc);
                vc_cons[currcons].d = NULL;
                return -ENOMEM;
                put_pid(vc->vt_pid);
                module_put(vc->vc_sw->owner);
                kfree(vc->vc_screenbuf);
-               if (currcons >= MIN_NR_CONSOLES)
+               if (currcons >= MIN_NR_CONSOLES) {
+                       tty_port_destroy(&vc->port);
                        kfree(vc);
+               }
                vc_cons[currcons].d = NULL;
        }
 }
 
 
        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;
 
                WARN_ON(port->port_usb != NULL);
 
+               tty_port_destroy(&port->port);
                kfree(port);
        }
        n_ports = 0;
 
        kfifo_free(&port->write_fifo);
        kfree(port->interrupt_in_buffer);
        kfree(port->interrupt_out_buffer);
+       tty_port_destroy(&port->port);
        kfree(port);
 }
 
 
        ircomm_tty_shutdown(self);
 
        self->magic = 0;
+       tty_port_destroy(&self->port);
        kfree(self);
 }