/* * Must be called before ipwireless_network_free(). */ void ipwireless_tty_free(struct ipw_tty *tty) { int j; struct ipw_network *network = ttys[tty->index]->network; for (j = tty->index; j < IPWIRELESS_PCMCIA_MINORS; j += IPWIRELESS_PCMCIA_MINOR_RANGE) { struct ipw_tty *ttyj = ttys[j]; if (ttyj) { mutex_lock(&ttyj->ipw_tty_mutex); if (get_tty(j + ipw_tty_driver->minor_start) == ttyj) report_deregistering(ttyj); ttyj->closing = 1; if (ttyj->linux_tty != NULL) { mutex_unlock(&ttyj->ipw_tty_mutex); tty_hangup(ttyj->linux_tty); /* Wait till the tty_hangup has completed */ flush_scheduled_work(); /* FIXME: Exactly how is the tty object locked here against a parallel ioctl etc */ mutex_lock(&ttyj->ipw_tty_mutex); } while (atomic_read(&ttyj->open_count)) do_ipw_close(ttyj); ipwireless_disassociate_network_ttys(network, ttyj->channel_idx); tty_unregister_device(ipw_tty_driver, j); ttys[j] = NULL; mutex_unlock(&ttyj->ipw_tty_mutex); kfree(ttyj); } } }
static void ipw_hangup(struct tty_struct *linux_tty) { struct ipw_tty *tty = linux_tty->driver_data; if (!tty) return; mutex_lock(&tty->ipw_tty_mutex); if (atomic_read(&tty->open_count) == 0) { mutex_unlock(&tty->ipw_tty_mutex); return; } do_ipw_close(tty); mutex_unlock(&tty->ipw_tty_mutex); }
/* * Must be called before ipwireless_network_free(). */ void ipwireless_tty_free(struct ipw_tty *tty) { int j; struct ipw_network *network = ttys[tty->index]->network; for (j = tty->index; j < IPWIRELESS_PCMCIA_MINORS; j += IPWIRELESS_PCMCIA_MINOR_RANGE) { struct ipw_tty *ttyj = ttys[j]; if (ttyj) { mutex_lock(&ttyj->ipw_tty_mutex); if (get_tty(j)) printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": deregistering %s device ttyIPWp%d\n", tty_type_name(ttyj->tty_type), j); ttyj->closing = 1; if (ttyj->port.tty != NULL) { mutex_unlock(&ttyj->ipw_tty_mutex); tty_vhangup(ttyj->port.tty); /* FIXME: Exactly how is the tty object locked here against a parallel ioctl etc */ /* FIXME2: hangup does not mean all processes * are gone */ mutex_lock(&ttyj->ipw_tty_mutex); } while (ttyj->port.count) do_ipw_close(ttyj); 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); } } }