Example #1
0
static void acm_tty_unregister(struct acm *acm)
{
	int i, nr;

	nr = acm->rx_buflimit;
	tty_unregister_device(acm_tty_driver, acm->minor);
	usb_put_intf(acm->control);
	acm_table[acm->minor] = NULL;
	usb_free_urb(acm->ctrlurb);
	for (i = 0; i < ACM_NW; i++)
		usb_free_urb(acm->wb[i].urb);
	for (i = 0; i < nr; i++)
		usb_free_urb(acm->ru[i].urb);
	kfree(acm->country_codes);
	kfree(acm);
}
void atcmd_cleanup(void)
{
    if (!at_tty_driver)
        return;

    tty_unregister_device(at_tty_driver, 0);
    tty_unregister_driver(at_tty_driver);
    put_tty_driver(at_tty_driver);
    at_tty_driver = NULL;

#ifdef ENABLE_DUMMY_HSIC_TTY
    hsic_cleanup();
#endif

    pr_debug("%s: cleaned up ttyGS0 support\n", __func__);
}
void gserial_free_line(unsigned char port_num)
{
    struct gs_port	*port;

    mutex_lock(&ports[port_num].lock);
    if (WARN_ON(!ports[port_num].port)) {
        mutex_unlock(&ports[port_num].lock);
        return;
    }
    port = ports[port_num].port;
    ports[port_num].port = NULL;
    mutex_unlock(&ports[port_num].lock);

    gserial_free_port(port);
    tty_unregister_device(gs_tty_driver, port_num);
}
/**
 * gserial_cleanup - remove TTY-over-USB driver and devices
 * Context: may sleep
 *
 * This is called to free all resources allocated by @gserial_setup().
 * Accordingly, it may need to wait until some open /dev/ files have
 * closed.
 *
 * The caller must have issued @gserial_disconnect() for any ports
 * that had previously been connected, so that there is never any
 * I/O pending when it's called.
 */
void gserial_cleanup(void)
{
    unsigned	i;
    struct gs_port	*port;
    int ret;

    if (!gs_tty_driver)
        return;

    /* start sysfs and /dev/ttyGS* node removal */
    for (i = 0; i < n_ports; i++)
        tty_unregister_device(gs_tty_driver, i);

    for (i = 0; i < n_ports; i++) {
        /* prevent new opens */
        mutex_lock(&ports[i].lock);
        port = ports[i].port;
        ports[i].port = NULL;
        mutex_unlock(&ports[i].lock);

        cancel_work_sync(&port->push);

        /* wait for old opens to finish */
        /*
         * port-bridge application will hold one file descriptor to gserial after usb mode switch sometimes
         * so wait_event will never get out ,further block kernel thread "suspend" and  block console_early_suspend
         * which makes the whole system hang.
         */
#if 0
        wait_event(port->close_wait, gs_closed(port));
#else
        ret = wait_event_timeout(port->close_wait, gs_closed(port),HZ/10);
        pr_debug("%s timeout %d  <\n",__func__,ret);
#endif

        WARN_ON(port->port_usb != NULL);

        kfree(port);
    }
    n_ports = 0;

    destroy_workqueue(gserial_wq);
    tty_unregister_driver(gs_tty_driver);
    gs_tty_driver = NULL;

    pr_debug("%s: cleaned up ttyGS* support\n", __func__);
}
Example #5
0
static int goldfish_tty_remove(struct platform_device *pdev)
{
	struct goldfish_tty *qtty = platform_get_drvdata(pdev);

	mutex_lock(&goldfish_tty_lock);

	unregister_console(&qtty->console);
	tty_unregister_device(goldfish_tty_driver, qtty->console.index);
	iounmap(qtty->base);
	qtty->base = NULL;
	free_irq(qtty->irq, pdev);
	goldfish_tty_current_line_count--;
	if (goldfish_tty_current_line_count == 0)
		goldfish_tty_delete_driver();
	mutex_unlock(&goldfish_tty_lock);
	return 0;
}
Example #6
0
static void __ipoctal_remove(struct ipoctal *ipoctal)
{
	int i;

	ipoctal->dev->bus->ops->free_irq(ipoctal->dev);

	for (i = 0; i < NR_CHANNELS; i++) {
		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);
	put_tty_driver(ipoctal->tty_drv);
	kfree(ipoctal);
}
Example #7
0
/**
 * gserial_cleanup - remove TTY-over-USB driver and devices
 * Context: may sleep
 *
 * This is called to free all resources allocated by @gserial_setup().
 * Accordingly, it may need to wait until some open /dev/ files have
 * closed.
 *
 * The caller must have issued @gserial_disconnect() for any ports
 * that had previously been connected, so that there is never any
 * I/O pending when it's called.
 */
void gserial_cleanup(void)
{
	unsigned	i;
	struct gs_port	*port;

	if (!gs_tty_driver)
		return;

	/* start sysfs and /dev/ttyGS* node removal */
	pr_info("gs_cleanup: unregister tty!\n");
	for (i = 0; i < n_ports; i++)
		tty_unregister_device(gs_tty_driver, i);
	pr_info("gs_cleanup: wait port close!\n");
	for (i = 0; i < n_ports; i++) {
		/* prevent new opens */
		mutex_lock(&ports[i].lock);
		port = ports[i].port;
		ports[i].port = NULL;
		mutex_unlock(&ports[i].lock);

		tasklet_kill(&port->push);

		pr_info("gs_cleanup: port%d++\n", i);
		/* wait for old opens to finish */
		wait_event_timeout(port->close_wait, gs_closed(port), 2*HZ);
		if(!gs_closed(port)){
			pr_info("%s: port %d still open, forcely close it!\n", __func__, i);
			gs_close_forcely(port);
			pr_info("%s: wait port %d close event again!\n", __func__, i);
			wait_event(port->close_wait, gs_closed(port));
			pr_info("%s: wait port %d close event done!\n", __func__, i);
		}

		pr_info("gs_cleanup: port%d--\n", i);
		WARN_ON(port->port_usb != NULL);

		kfree(port);
	}
	n_ports = 0;

	tty_unregister_driver(gs_tty_driver);
	gs_tty_driver = NULL;

	pr_info("%s: cleaned up ttyGS* support\n", __func__);
}
Example #8
0
static void tty_exit(struct nozomi *dc)
{
	unsigned int i;

	DBG1(" ");

	for (i = 0; i < MAX_PORT; ++i)
		tty_port_tty_hangup(&dc->port[i].port, false);

	/* Racy below - surely should wait for scheduled work to be done or
	   complete off a hangup method ? */
	while (dc->open_ttys)
		msleep(1);
	for (i = 0; i < MAX_PORT; ++i) {
		tty_unregister_device(ntty_driver, dc->index_start + i);
		tty_port_destroy(&dc->port[i].port);
	}
}
Example #9
0
void micvcons_destroy(int num_bds)
{
	int bd, ret;
	micvcons_port_t *port;

	if (!micvcons_tty)
		return;
	for (bd = 0; bd < num_bds; bd++) {
		port = &mic_data.dd_ports[bd];
		destroy_workqueue(port->dp_wq);
		tty_unregister_device(micvcons_tty, bd);
	}
	ret = tty_unregister_driver(micvcons_tty);
	put_tty_driver(micvcons_tty);
	micvcons_tty = NULL;

	if (ret)
		printk(KERN_ERR "tty unregister_driver failed with code %d\n", ret);
}
/* Diag char driver no longer ready */
void tty_diag_channel_close(struct usb_diag_ch *diag_ch)
{
	struct diag_tty_data *priv_usb = diag_ch->priv_usb;
	unsigned long flags;
	int i;

	if (diag_ch->priv_usb) {
		tty_insert_flip_char(&priv_usb->port, 0x00, TTY_BREAK);
		tty_flip_buffer_push(&priv_usb->port);
	}
	spin_lock_irqsave(&diag_tty_lock, flags);
	diag_ch->priv = NULL;
	diag_ch->notify = NULL;

	for (i = DIAG_TTY_MINOR_COUNT - 1; i >= 0; i--)
		tty_unregister_device(diag_tty_driver, i);

	spin_unlock_irqrestore(&diag_tty_lock, flags);
}
Example #11
0
/**
 * gserial_cleanup - remove TTY-over-USB driver and devices
 * Context: may sleep
 *
 * This is called to free all resources allocated by @gserial_setup().
 * Accordingly, it may need to wait until some open /dev/ files have
 * closed.
 *
 * The caller must have issued @gserial_disconnect() for any ports
 * that had previously been connected, so that there is never any
 * I/O pending when it's called.
 */
void gserial_cleanup(void)
{
	unsigned	i;
	struct gs_port	*port;
	int ret;

	if (!gs_tty_driver)
		return;

	/* start sysfs and /dev/ttyGS* node removal */
	for (i = 0; i < n_ports; i++)
		tty_unregister_device(gs_tty_driver, i);

	for (i = 0; i < n_ports; i++) {
		/* prevent new opens */
		mutex_lock(&ports[i].lock);
		port = ports[i].port;
		ports[i].port = NULL;
		mutex_unlock(&ports[i].lock);

		cancel_work_sync(&port->push);

		/* wait for old opens to finish */
#if 0
		wait_event(port->close_wait, gs_closed(port));
#else
		ret = wait_event_timeout(port->close_wait, gs_closed(port),HZ/10);
		pr_debug("%s timeout %d  <\n",__func__,ret);
#endif

		WARN_ON(port->port_usb != NULL);

		kfree(port);
	}
	n_ports = 0;

	destroy_workqueue(gserial_wq);
	tty_unregister_driver(gs_tty_driver);
	put_tty_driver(gs_tty_driver);
	gs_tty_driver = NULL;

	pr_debug("%s: cleaned up ttyGS* support\n", __func__);
}
/**
 * gserial_cleanup - remove TTY-over-USB driver and devices
 * Context: may sleep
 *
 * This is called to free all resources allocated by @gserial_setup().
 * Accordingly, it may need to wait until some open /dev/ files have
 * closed.
 *
 * The caller must have issued @gserial_disconnect() for any ports
 * that had previously been connected, so that there is never any
 * I/O pending when it's called.
 */
void gserial_cleanup(void)
{
	unsigned	i;
	struct gs_port	*port;

	if (!gs_tty_driver)
		return;

	/* start sysfs and /dev/ttyGS* node removal */
	for (i = 0; i < n_ports; i++)
		tty_unregister_device(gs_tty_driver, i);

	for (i = 0; i < n_ports; i++) {
		/* prevent new opens */
		mutex_lock(&ports[i].lock);
		port = ports[i].port;

#ifdef CONFIG_USB_G_SERIAL_CONSOLE
//	unregister_console(&port->port_console);
#endif
		ports[i].port = NULL;

		mutex_unlock(&ports[i].lock);

		cancel_work_sync(&port->push);

		/* wait for old opens to finish */
		wait_event(port->close_wait, gs_closed(port));

		WARN_ON(port->port_usb != NULL);

		kfree(port);
	}
	n_ports = 0;

	destroy_workqueue(gserial_wq);
	tty_unregister_driver(gs_tty_driver);
	put_tty_driver(gs_tty_driver);
	gs_tty_driver = NULL;

	pr_debug("%s: cleaned up ttyGS* support\n", __func__);
}
Example #13
0
static void __exit my_uart_exit(void)
{
    /* TODO Auto-generated Function Stub */

    int i;

    del_timer(&my_uart_timer);

    PINFO("EXIT\n");

    for (i = 0; i < MY_UART_N_MINORS; i++) {

        del_timer(&devices[i].my_uart_timer1);

        tty_unregister_device(my_uart_tty, i);
    }

    tty_unregister_driver(my_uart_tty);
    put_tty_driver(my_uart_tty);

}
Example #14
0
static void __exit spi_tty_exit(void)
{
	struct spi_tty_s *spi_tty;

	tty_unregister_device(spi_tty_driver, 0);
	tty_unregister_driver(spi_tty_driver);

	/* shut down all of the timers and free the memory */
	spi_tty = spi_tty_gbl;
	if (spi_tty) {
		/* close the port */
		while (spi_tty->open_count)
			do_close(spi_tty);

		spi_tty_buf_free(spi_tty->write_buf);
		wake_lock_destroy(&spi_tty->wakelock);

		//TODO: flush can destory work queue
		kfree(spi_tty);
		spi_tty_gbl = NULL;
	}
}
static void __exit lge_dm_tty_exit(void)
{
	int ret = 0;
	struct dm_tty *lge_dm_tty_drv = NULL;

	lge_dm_tty_drv = lge_dm_tty;

	if (!lge_dm_tty_drv) {
		pr_err(DM_TTY_MODULE_NAME ": %s:"
		"NULL lge_dm_tty_drv", __func__);
		return;
	}

	if (lge_dm_tty_drv->tty_state != DM_TTY_INITIAL) {
		tty_unregister_device(lge_dm_tty_drv->tty_drv, 0);

		ret = tty_unregister_driver(lge_dm_tty_drv->tty_drv);

		if (ret) {
			pr_err(DM_TTY_MODULE_NAME ": %s: "
			    "tty_unregister_driver() failed\n", __func__);
		}

		put_tty_driver(lge_dm_tty_drv->tty_drv);
		lge_dm_tty_drv->tty_state = DM_TTY_INITIAL;
		lge_dm_tty_drv->tty_drv = NULL;
	}

	kfree(dm_modem_response);
	kfree(dm_modem_request);
	kfree(dm_modem_response_header);
	kfree(dm_modem_response_body);

	pr_info(DM_TTY_MODULE_NAME ": %s: Freeing dm_tty structure", __func__);
	kfree(lge_dm_tty_drv);

	return;

}
/**
 * gserial_cleanup - remove TTY-over-USB driver and devices
 * Context: may sleep
 *
 * This is called to free all resources allocated by @gserial_setup().
 * Accordingly, it may need to wait until some open /dev/ files have
 * closed.
 *
 * The caller must have issued @gserial_disconnect() for any ports
 * that had previously been connected, so that there is never any
 * I/O pending when it's called.
 */
void gserial_cleanup(void)
{
	unsigned	i;
	struct gs_port	*port;

	if (!gs_tty_driver)
		return;

	/* start sysfs and /dev/ttyGS* node removal */
	for (i = 0; i < n_ports; i++)
		tty_unregister_device(gs_tty_driver, i);

	for (i = 0; i < n_ports; i++) {
		/* prevent new opens */
		mutex_lock(&ports[i].lock);
		port = ports[i].port;
		ports[i].port = NULL;
		mutex_unlock(&ports[i].lock);
#ifndef CONFIG_USE_WORKQ_PUSH
		tasklet_kill(&port->push);
#else
		flush_work_sync(&port->push);
#endif
		/* wait for old opens to finish */
		wait_event(port->close_wait, gs_closed(port));

		WARN_ON(port->port_usb != NULL);

		kfree(port);
	}
	n_ports = 0;

	tty_unregister_driver(gs_tty_driver);
	put_tty_driver(gs_tty_driver);
	gs_tty_driver = NULL;

	pr_debug("%s: cleaned up ttyGS* support\n", __func__);
}
Example #17
0
void gserial_cleanup(void)
{
	unsigned	i;
	struct gs_port	*port;

	if (!gs_tty_driver)
		return;

	
	for (i = 0; i < n_ports; i++)
		tty_unregister_device(gs_tty_driver, i);

	for (i = 0; i < n_ports; i++) {
		
		mutex_lock(&ports[i].lock);
		port = ports[i].port;
		ports[i].port = NULL;
		mutex_unlock(&ports[i].lock);

		cancel_work_sync(&port->push);

		
		wait_event(port->close_wait, gs_closed(port));

		WARN_ON(port->port_usb != NULL);

		kfree(port);
	}
	n_ports = 0;

	usb_debugfs_remove();
	destroy_workqueue(gserial_wq);
	tty_unregister_driver(gs_tty_driver);
	put_tty_driver(gs_tty_driver);
	gs_tty_driver = NULL;

	pr_debug("%s: cleaned up ttyGS* support\n", __func__);
}
Example #18
0
static void __exit nullmodem_exit(void)
{
	int i;

	dprintf("%s - \n", __FUNCTION__);

	del_timer_sync(&nullmodem_timer);

	for (i = 0; i < NULLMODEM_PAIRS*2; ++i)
	{
		tty_unregister_device(nullmodem_tty_driver, i);
		tty_port_destroy(&tport[i]);
	}
	tty_unregister_driver(nullmodem_tty_driver);

	/* shut down all of the timers and free the memory */
	for (i = 0; i < NULLMODEM_PAIRS; ++i)
	{
		pair_table[i].a.tty = NULL;
		pair_table[i].b.tty = NULL;
	}
	kfree(tport);
}
Example #19
0
/*
 * 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);
		}
	}
}
Example #20
0
void cbob_uart_exit(void)
{
	struct cbob_uart *uart;
	int i;
	
	free_irq(IRQ_GPIOD(27), 0);
	
	for(i = 0;i < CBOB_UART_MINORS;i++)
		tty_unregister_device(cbob_uart_tty_driver, i);
	tty_unregister_driver(cbob_uart_tty_driver);
	
	for(i = 0;i < CBOB_UART_MINORS;i++) {
		uart = cbob_uarts[i];
		if(uart) {
			while(uart->open_count)
				do_close(uart);
			kfree(uart);
			cbob_uarts[i] = NULL;
		}
	}
	
	flush_workqueue(cbob_uart_workqueue);
	destroy_workqueue(cbob_uart_workqueue);
}
Example #21
0
static int goldfish_tty_probe(struct platform_device *pdev)
{
	int ret;
	int i;
	struct resource *r;
	struct device *ttydev;
	uint32_t base;
	uint32_t irq;

	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if(r == NULL)
		return -EINVAL;
	base = IO_ADDRESS(r->start - IO_START);
	r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if(r == NULL)
		return -EINVAL;
	irq = r->start;

	if(pdev->id >= goldfish_tty_line_count)
		return -EINVAL;

	mutex_lock(&goldfish_tty_lock);
	if(goldfish_tty_current_line_count == 0) {
		ret = goldfish_tty_create_driver();
		if(ret)
			goto err_create_driver_failed;
	}
	goldfish_tty_current_line_count++;

	spin_lock_init(&goldfish_ttys[pdev->id].lock);
	goldfish_ttys[pdev->id].base = base;
	goldfish_ttys[pdev->id].irq = irq;

	writel(GOLDFISH_TTY_CMD_INT_DISABLE, base + GOLDFISH_TTY_CMD);

	ret = request_irq(irq, goldfish_tty_interrupt, IRQF_SHARED, "goldfish_tty", pdev);
	if(ret)
		goto err_request_irq_failed;


	ttydev = tty_register_device(goldfish_tty_driver, pdev->id, NULL);
	if(IS_ERR(ttydev)) {
		ret = PTR_ERR(ttydev);
		goto err_tty_register_device_failed;
	}

	strcpy(goldfish_ttys[pdev->id].console.name, "ttyS");
	goldfish_ttys[pdev->id].console.write		= goldfish_tty_console_write;
	goldfish_ttys[pdev->id].console.device		= goldfish_tty_console_device;
	goldfish_ttys[pdev->id].console.setup		= goldfish_tty_console_setup;
	goldfish_ttys[pdev->id].console.flags		= CON_PRINTBUFFER;
	goldfish_ttys[pdev->id].console.index		= pdev->id;
	register_console(&goldfish_ttys[pdev->id].console);


	mutex_unlock(&goldfish_tty_lock);

	return 0;

	tty_unregister_device(goldfish_tty_driver, i);
err_tty_register_device_failed:
	free_irq(irq, pdev);
err_request_irq_failed:
	goldfish_tty_current_line_count--;
	if(goldfish_tty_current_line_count == 0) {
		goldfish_tty_delete_driver();
	}
err_create_driver_failed:
	mutex_unlock(&goldfish_tty_lock);
	return ret;
}
Example #22
0
static int __init smd_tty_init(void)
{
	int ret;
	int n;
	int idx;

	smd_tty_driver = alloc_tty_driver(MAX_SMD_TTYS);
	if (smd_tty_driver == 0)
		return -ENOMEM;

	smd_tty_driver->owner = THIS_MODULE;
	smd_tty_driver->driver_name = "smd_tty_driver";
	smd_tty_driver->name = "smd";
	smd_tty_driver->major = 0;
	smd_tty_driver->minor_start = 0;
	smd_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
	smd_tty_driver->subtype = SERIAL_TYPE_NORMAL;
	smd_tty_driver->init_termios = tty_std_termios;
	smd_tty_driver->init_termios.c_iflag = 0;
	smd_tty_driver->init_termios.c_oflag = 0;
	smd_tty_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
	smd_tty_driver->init_termios.c_lflag = 0;
	smd_tty_driver->flags = TTY_DRIVER_RESET_TERMIOS |
		TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
	tty_set_operations(smd_tty_driver, &smd_tty_ops);

	ret = tty_register_driver(smd_tty_driver);
	if (ret) {
		put_tty_driver(smd_tty_driver);
		pr_err("%s: driver registration failed %d\n", __func__, ret);
		return ret;
	}

	for (n = 0; n < ARRAY_SIZE(smd_configs); ++n) {
		idx = smd_configs[n].tty_dev_index;

		if (smd_configs[n].dev_name == NULL)
			smd_configs[n].dev_name = smd_configs[n].port_name;

		if (idx == DS_IDX) {
			/*
			 * DS port uses the kernel API starting with
			 * 8660 Fusion.  Only register the userspace
			 * platform device for older targets.
			 */
			int legacy_ds = 0;

			legacy_ds |= cpu_is_msm7x01() || cpu_is_msm7x25();
			legacy_ds |= cpu_is_msm7x27() || cpu_is_msm7x30();
			legacy_ds |= cpu_is_qsd8x50() || cpu_is_msm8x55();
			/*
			 * use legacy mode for 8660 Standalone (subtype 0)
			 */
			legacy_ds |= cpu_is_msm8x60() &&
					(socinfo_get_platform_subtype() == 0x0);

			if (!legacy_ds)
				continue;
		}

		tty_register_device(smd_tty_driver, idx, 0);
		init_completion(&smd_tty[idx].ch_allocated);

		/* register platform device */
		smd_tty[idx].driver.probe = smd_tty_dummy_probe;
		smd_tty[idx].driver.driver.name = smd_configs[n].dev_name;
		smd_tty[idx].driver.driver.owner = THIS_MODULE;
		spin_lock_init(&smd_tty[idx].reset_lock);
		smd_tty[idx].is_open = 0;
		init_waitqueue_head(&smd_tty[idx].ch_opened_wait_queue);
		ret = platform_driver_register(&smd_tty[idx].driver);

		if (ret) {
			pr_err("%s: init failed %d (%d)\n", __func__, idx, ret);
			smd_tty[idx].driver.probe = NULL;
			goto out;
		}
		smd_tty[idx].smd = &smd_configs[n];
	}
	INIT_DELAYED_WORK(&loopback_work, loopback_probe_worker);
	return 0;

out:
	/* unregister platform devices */
	for (n = 0; n < ARRAY_SIZE(smd_configs); ++n) {
		idx = smd_configs[n].tty_dev_index;

		if (smd_tty[idx].driver.probe) {
			platform_driver_unregister(&smd_tty[idx].driver);
			tty_unregister_device(smd_tty_driver, idx);
		}
	}

	tty_unregister_driver(smd_tty_driver);
	put_tty_driver(smd_tty_driver);
	return ret;
}
Example #23
0
void ec_tty_clear(ec_tty_t *tty)
{
    del_timer_sync(&tty->timer);
    tty_unregister_device(tty_driver, tty->minor);
}
Example #24
0
/* Allocate memory for one device */
static int nozomi_card_init(struct pci_dev *pdev,
				      const struct pci_device_id *ent)
{
	resource_size_t start;
	int ret;
	struct nozomi *dc = NULL;
	int ndev_idx;
	int i;

	dev_dbg(&pdev->dev, "Init, new card found\n");

	for (ndev_idx = 0; ndev_idx < ARRAY_SIZE(ndevs); ndev_idx++)
		if (!ndevs[ndev_idx])
			break;

	if (ndev_idx >= ARRAY_SIZE(ndevs)) {
		dev_err(&pdev->dev, "no free tty range for this card left\n");
		ret = -EIO;
		goto err;
	}

	dc = kzalloc(sizeof(struct nozomi), GFP_KERNEL);
	if (unlikely(!dc)) {
		dev_err(&pdev->dev, "Could not allocate memory\n");
		ret = -ENOMEM;
		goto err_free;
	}

	dc->pdev = pdev;

	ret = pci_enable_device(dc->pdev);
	if (ret) {
		dev_err(&pdev->dev, "Failed to enable PCI Device\n");
		goto err_free;
	}

	ret = pci_request_regions(dc->pdev, NOZOMI_NAME);
	if (ret) {
		dev_err(&pdev->dev, "I/O address 0x%04x already in use\n",
			(int) /* nozomi_private.io_addr */ 0);
		goto err_disable_device;
	}

	start = pci_resource_start(dc->pdev, 0);
	if (start == 0) {
		dev_err(&pdev->dev, "No I/O address for card detected\n");
		ret = -ENODEV;
		goto err_rel_regs;
	}

	/* Find out what card type it is */
	nozomi_get_card_type(dc);

	dc->base_addr = ioremap_nocache(start, dc->card_type);
	if (!dc->base_addr) {
		dev_err(&pdev->dev, "Unable to map card MMIO\n");
		ret = -ENODEV;
		goto err_rel_regs;
	}

	dc->send_buf = kmalloc(SEND_BUF_MAX, GFP_KERNEL);
	if (!dc->send_buf) {
		dev_err(&pdev->dev, "Could not allocate send buffer?\n");
		ret = -ENOMEM;
		goto err_free_sbuf;
	}

	for (i = PORT_MDM; i < MAX_PORT; i++) {
		if (kfifo_alloc(&dc->port[i].fifo_ul, FIFO_BUFFER_SIZE_UL,
					GFP_KERNEL)) {
			dev_err(&pdev->dev,
					"Could not allocate kfifo buffer\n");
			ret = -ENOMEM;
			goto err_free_kfifo;
		}
	}

	spin_lock_init(&dc->spin_mutex);

	nozomi_setup_private_data(dc);

	/* Disable all interrupts */
	dc->last_ier = 0;
	writew(dc->last_ier, dc->reg_ier);

	ret = request_irq(pdev->irq, &interrupt_handler, IRQF_SHARED,
			NOZOMI_NAME, dc);
	if (unlikely(ret)) {
		dev_err(&pdev->dev, "can't request irq %d\n", pdev->irq);
		goto err_free_kfifo;
	}

	DBG1("base_addr: %p", dc->base_addr);

	make_sysfs_files(dc);

	dc->index_start = ndev_idx * MAX_PORT;
	ndevs[ndev_idx] = dc;

	pci_set_drvdata(pdev, dc);

	/* Enable RESET interrupt */
	dc->last_ier = RESET;
	iowrite16(dc->last_ier, dc->reg_ier);

	dc->state = NOZOMI_STATE_ENABLED;

	for (i = 0; i < MAX_PORT; i++) {
		struct device *tty_dev;
		struct port *port = &dc->port[i];
		port->dc = dc;
		tty_port_init(&port->port);
		port->port.ops = &noz_tty_port_ops;
		tty_dev = tty_port_register_device(&port->port, ntty_driver,
				dc->index_start + i, &pdev->dev);

		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 = 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);
err_free_sbuf:
	kfree(dc->send_buf);
	iounmap(dc->base_addr);
err_rel_regs:
	pci_release_regions(pdev);
err_disable_device:
	pci_disable_device(pdev);
err_free:
	kfree(dc);
err:
	return ret;
}
Example #25
0
static int __init smd_tty_init(void)
{
	int ret;
	int n;
	int idx;

	smd_tty_driver = alloc_tty_driver(MAX_SMD_TTYS);
	if (smd_tty_driver == 0)
		return -ENOMEM;

	smd_tty_driver->owner = THIS_MODULE;
	smd_tty_driver->driver_name = "smd_tty_driver";
	smd_tty_driver->name = "smd";
	smd_tty_driver->major = 0;
	smd_tty_driver->minor_start = 0;
	smd_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
	smd_tty_driver->subtype = SERIAL_TYPE_NORMAL;
	smd_tty_driver->init_termios = tty_std_termios;
	smd_tty_driver->init_termios.c_iflag = 0;
	smd_tty_driver->init_termios.c_oflag = 0;
	smd_tty_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
	smd_tty_driver->init_termios.c_lflag = 0;
	smd_tty_driver->flags = TTY_DRIVER_RESET_TERMIOS |
		TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
	tty_set_operations(smd_tty_driver, &smd_tty_ops);

	ret = tty_register_driver(smd_tty_driver);
	if (ret) {
		put_tty_driver(smd_tty_driver);
		pr_err("%s: driver registration failed %d\n", __func__, ret);
		return ret;
	}

	for (n = 0; n < ARRAY_SIZE(smd_configs); ++n) {
		idx = smd_configs[n].tty_dev_index;

		if (smd_configs[n].dev_name == NULL)
			smd_configs[n].dev_name = smd_configs[n].port_name;

		if (idx == DS_IDX) {
			int legacy_ds = 0;

			legacy_ds |= cpu_is_msm7x01() || cpu_is_msm7x25();
			legacy_ds |= cpu_is_msm7x27() || cpu_is_msm7x30();
			legacy_ds |= cpu_is_qsd8x50() || cpu_is_msm8x55();
			legacy_ds |= (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8930aa()) && (board_mfg_mode() == 8);
			legacy_ds |= cpu_is_msm8x60() &&
					(socinfo_get_platform_subtype() == 0x0);
			#ifdef CONFIG_MACH_DUMMY
			legacy_ds = 1;
			#endif

			if (!legacy_ds)
				continue;
		}

		tty_register_device(smd_tty_driver, idx, 0);
		init_completion(&smd_tty[idx].ch_allocated);

		
		smd_tty[idx].driver.probe = smd_tty_dummy_probe;
		smd_tty[idx].driver.driver.name = smd_configs[n].dev_name;
		smd_tty[idx].driver.driver.owner = THIS_MODULE;
		spin_lock_init(&smd_tty[idx].reset_lock);
		smd_tty[idx].is_open = 0;
		setup_timer(&smd_tty[idx].buf_req_timer, buf_req_retry,
				(unsigned long)&smd_tty[idx]);
		init_waitqueue_head(&smd_tty[idx].ch_opened_wait_queue);
		ret = platform_driver_register(&smd_tty[idx].driver);

		if (ret) {
			pr_err("%s: init failed %d (%d)\n", __func__, idx, ret);
			smd_tty[idx].driver.probe = NULL;
			goto out;
		}
		smd_tty[idx].smd = &smd_configs[n];
	}
	INIT_DELAYED_WORK(&loopback_work, loopback_probe_worker);
	return 0;

out:
	
	for (n = 0; n < ARRAY_SIZE(smd_configs); ++n) {
		idx = smd_configs[n].tty_dev_index;

		if (smd_tty[idx].driver.probe) {
			platform_driver_unregister(&smd_tty[idx].driver);
			tty_unregister_device(smd_tty_driver, idx);
		}
	}

	tty_unregister_driver(smd_tty_driver);
	put_tty_driver(smd_tty_driver);
	return ret;
}
Example #26
0
static int ipoctal_install_all(void)
{
	int i, j, t;
	int res = 0;
	struct tty_driver *tty;
	char name[20] = "";

	ipoctal_installed = (struct ipoctal*) kzalloc(num_lun * sizeof(struct ipoctal), GFP_KERNEL);
	if (ipoctal_installed == NULL) {
		printk(KERN_ERR PFX "Unable to allocate memory for ipoctal's !\n");
		res = -ENOMEM;
		goto out_err;
	}

	for (i=0; i<num_lun;i++) {
		tty = alloc_tty_driver(NR_CHANNELS);

		if(!tty)
			return -ENOMEM;

		tty->owner = THIS_MODULE;
		tty->driver_name = "ipoctal";
		sprintf(name, "ipoctal.%d.", lun[i]);
		tty->name = name;
		tty->major = 0;

		tty->minor_start = 0;
		tty->type = TTY_DRIVER_TYPE_SERIAL;
		tty->subtype = SERIAL_TYPE_NORMAL;
		tty->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
		tty->init_termios = tty_std_termios;
		tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
		tty->init_termios.c_ispeed = 9600;
		tty->init_termios.c_ospeed = 9600;
		tty->init_termios.c_iflag = tty_std_termios.c_iflag | IGNBRK;

		tty_set_operations(tty, &ipoctalFops);
		res = tty_register_driver(tty);
		if(res) {
			printk(KERN_ERR PFX "Can't register tty driver.\n");
			put_tty_driver(tty);
			goto out_uninst;
		}

		for(j = 0; j < NR_CHANNELS;j++) {
			tty_register_device(tty, j, NULL);
			ipoctal_installed[i].tty[j] = NULL;
			spin_lock_init(&ipoctal_installed[i].lock[j]);
			mutex_init(&ipoctal_installed[i].lock_write[j]);
			ipoctal_installed[i].pointer_read[j] = 0;
			ipoctal_installed[i].pointer_write[j] = 0;
			ipoctal_installed[i].nb_bytes[j] = 0;
		}
		ipoctal_installed[i].tty_drv = tty;
		ipoctal_installed[i].index = i;

		res = ipoctal_inst_slot(&ipoctal_installed[i],
				carrier_number[i],
				slot[i],
				irq[i],
				carrier[i]);
		if (res) {
			printk(KERN_ERR PFX "Error during IP octal install !\n");
			goto out_uninst;
		}	
	}

	return 0;

out_uninst :
	for (j=0; j < i;j++){
		for (t = 0; t < NR_CHANNELS; t++)
			tty_unregister_device(ipoctal_installed[j].tty_drv, t);
		tty_unregister_driver(ipoctal_installed[j].tty_drv);
		ipoctal_uninst_slot(&ipoctal_installed[j]);
	}
	kfree(ipoctal_installed);
	ipoctal_installed = NULL;
	printk(KERN_ERR PFX "Unregistered all IP octal devices\n");
out_err :
	return res;
}
Example #27
0
static int __init smd_tty_init(void)
{
	int ret;
	int n;
	int idx;
	struct tty_port *port;

	smd_tty_log_init();
	smd_tty_driver = alloc_tty_driver(MAX_SMD_TTYS);
	if (smd_tty_driver == 0) {
		SMD_TTY_ERR("%s - Driver allocation failed", __func__);
		return -ENOMEM;
	}

	smd_tty_driver->owner = THIS_MODULE;
	smd_tty_driver->driver_name = "smd_tty_driver";
	smd_tty_driver->name = "smd";
	smd_tty_driver->major = 0;
	smd_tty_driver->minor_start = 0;
	smd_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
	smd_tty_driver->subtype = SERIAL_TYPE_NORMAL;
	smd_tty_driver->init_termios = tty_std_termios;
	smd_tty_driver->init_termios.c_iflag = 0;
	smd_tty_driver->init_termios.c_oflag = 0;
	smd_tty_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
	smd_tty_driver->init_termios.c_lflag = 0;
	smd_tty_driver->flags = TTY_DRIVER_RESET_TERMIOS |
		TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
	tty_set_operations(smd_tty_driver, &smd_tty_ops);

	ret = tty_register_driver(smd_tty_driver);
	if (ret) {
		put_tty_driver(smd_tty_driver);
		SMD_TTY_ERR("%s: driver registration failed %d", __func__, ret);
		return ret;
	}

	for (n = 0; n < ARRAY_SIZE(smd_configs); ++n) {
		idx = smd_configs[n].tty_dev_index;

		if (smd_configs[n].dev_name == NULL)
			smd_configs[n].dev_name = smd_configs[n].port_name;

		if (idx == DS_IDX) {
			/*
			 * DS port uses the kernel API starting with
			 * 8660 Fusion.  Only register the userspace
			 * platform device for older targets.
			 */
			int legacy_ds = 0;

			legacy_ds |= cpu_is_msm7x01() || cpu_is_msm7x25();
			legacy_ds |= cpu_is_msm7x27() || cpu_is_msm7x30();
			legacy_ds |= cpu_is_qsd8x50() || cpu_is_msm8x55();
			/*
			 * use legacy mode for 8660 Standalone (subtype 0)
			 */
			legacy_ds |= cpu_is_msm8x60() &&
					(socinfo_get_platform_subtype() == 0x0);
#ifdef CONFIG_MSM_SMD_TTY_DS_LEGACY
			legacy_ds |= cpu_is_msm8974();
#endif

			if (!legacy_ds)
				continue;
		}

		port = &smd_tty[idx].port;
		tty_port_init(port);
		port->ops = &smd_tty_port_ops;
		/* TODO: For kernel >= 3.7 use tty_port_register_device */
		smd_tty[idx].device_ptr =
			tty_register_device(smd_tty_driver, idx, 0);
		if (device_create_file(smd_tty[idx].device_ptr,
					&dev_attr_open_timeout))
			SMD_TTY_ERR(
				"%s: Unable to create device attributes for %s",
				__func__, smd_configs[n].port_name);

		init_completion(&smd_tty[idx].ch_allocated);

		/* register platform device */
		smd_tty[idx].driver.probe = smd_tty_dummy_probe;
#ifdef CONFIG_MSM_SMD_TTY_DS_LEGACY
		if (idx == DS_IDX) {
			/* register platform device for DS */
			smd_tty[idx].driver.probe = smd_tty_ds_probe;
			smd_tty[idx].is_dsmodem_ready = 0;
		}
#endif
		smd_tty[idx].driver.driver.name = smd_configs[n].dev_name;
		smd_tty[idx].driver.driver.owner = THIS_MODULE;
		spin_lock_init(&smd_tty[idx].reset_lock);
		spin_lock_init(&smd_tty[idx].ra_lock);
		smd_tty[idx].is_open = 0;
		setup_timer(&smd_tty[idx].buf_req_timer, buf_req_retry,
				(unsigned long)&smd_tty[idx]);
		init_waitqueue_head(&smd_tty[idx].ch_opened_wait_queue);
		ret = platform_driver_register(&smd_tty[idx].driver);

		if (ret) {
			SMD_TTY_ERR(
				"%s: init failed %d (%d)", __func__, idx, ret);
			smd_tty[idx].driver.probe = NULL;
			goto out;
		}
		smd_tty[idx].smd = &smd_configs[n];
	}
	INIT_DELAYED_WORK(&loopback_work, loopback_probe_worker);
	return 0;

out:
	/* unregister platform devices */
	for (n = 0; n < ARRAY_SIZE(smd_configs); ++n) {
		idx = smd_configs[n].tty_dev_index;

		if (smd_tty[idx].driver.probe) {
			platform_driver_unregister(&smd_tty[idx].driver);
			tty_unregister_device(smd_tty_driver, idx);
		}
	}

	tty_unregister_driver(smd_tty_driver);
	put_tty_driver(smd_tty_driver);
	return ret;
}
Example #28
0
int
micvcons_create(int num_bds)
{
	micvcons_port_t *port;
	bd_info_t *bd_info;
	int bd, ret = 0;
	char wq_name[14];
	struct device *dev;

	INIT_LIST_HEAD(&timer_list_head);

	if (micvcons_tty)
		goto exit;

	micvcons_tty = alloc_tty_driver(num_bds);
	if (!micvcons_tty) {
		ret = -ENOMEM;
		goto exit;
	}
	micvcons_tty->owner = THIS_MODULE;
	micvcons_tty->driver_name = MICVCONS_DEVICE_NAME;
	micvcons_tty->name = MICVCONS_DEVICE_NAME;
	micvcons_tty->major = 0;
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)
	micvcons_tty->minor_num = num_bds;
#endif
	micvcons_tty->minor_start = 0;
	micvcons_tty->type = TTY_DRIVER_TYPE_SERIAL;
	micvcons_tty->subtype = SERIAL_TYPE_NORMAL;
	micvcons_tty->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
	micvcons_tty->init_termios = tty_std_termios;
	micvcons_tty->init_termios.c_iflag = IGNCR;
	micvcons_tty->init_termios.c_oflag = 0;
	micvcons_tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
	micvcons_tty->init_termios.c_lflag = 0;

	tty_set_operations(micvcons_tty, &micvcons_tty_ops);

	if ((ret = tty_register_driver(micvcons_tty)) != 0) {
		printk("Failed to register vcons tty driver\n");
		put_tty_driver(micvcons_tty);
		micvcons_tty = NULL;
		goto exit;
	}

	for (bd = 0; bd < num_bds; bd++) {
		port = &mic_data.dd_ports[bd];
		port->dp_bdinfo = mic_data.dd_bi[bd];

		spin_lock_init(&port->dp_lock);
		mutex_init (&port->dp_mutex);

		bd_info = (bd_info_t *)port->dp_bdinfo;
		bd_info->bi_port = port;

		dev = tty_register_device(micvcons_tty, bd, NULL);
		if (IS_ERR(dev)) {
			printk("Failed to register vcons tty device\n");
			micvcons_destroy(bd);
			ret = PTR_ERR(dev);
			goto exit;
		}
		snprintf(wq_name, sizeof(wq_name), "VCONS MIC %d", bd);
		port->dp_wq = create_singlethread_workqueue(wq_name);
		if (!port->dp_wq) {
			printk(KERN_ERR "%s: create_singlethread_workqueue\n", 
								__func__);
			tty_unregister_device(micvcons_tty, bd);
			micvcons_destroy(bd);
			ret = -ENOMEM;
			goto exit;
		}
		INIT_WORK(&port->dp_wakeup_read_buf, micvcons_wakeup_readbuf);
	}
	vcons_timer.function = micvcons_timeout;
	vcons_timer.data = (unsigned long)(&timer_list_head);
	init_timer(&vcons_timer);
exit:
	return ret;
}