static void mtk_wcn_stp_uart_exit(void)
{
    int err;

    mtk_wcn_stp_register_if_tx(STP_UART_IF_TX, NULL);    // unregister if_tx function

    /* Release tty registration of line discipline */
    if ((err = tty_unregister_ldisc(N_MTKSTP)))
    {
        UART_ERR_FUNC("Can't unregister MTK STP line discipline (%d)\n", err);
    }

#if (LDISC_RX == LDISC_RX_TASKLET)
    tasklet_kill(&g_stp_uart_rx_fifo_tasklet);
    stp_uart_fifo_deinit();
#elif (LDISC_RX == LDISC_RX_WORK)
	if (g_stp_uart_rx_work) {
		cancel_work_sync(g_stp_uart_rx_work);
	}
	if (g_stp_uart_rx_wq) {
		destroy_workqueue(g_stp_uart_rx_wq);
		g_stp_uart_rx_wq = NULL;
	}
	if (g_stp_uart_rx_work) {
		vfree(g_stp_uart_rx_work);
		g_stp_uart_rx_work = NULL;
	}
	stp_uart_fifo_deinit();

#endif
    return;
}
Beispiel #2
0
static void __exit mtk_wcn_stp_uart_exit(void)
{
    int err;

    mtk_wcn_stp_register_if_tx(STP_UART_IF_TX, NULL);    // unregister if_tx function

    /* Release tty registration of line discipline */
    if ((err = tty_unregister_ldisc(N_MTKSTP)))
    {
        UART_ERR_FUNC("Can't unregister MTK STP line discipline (%d)\n", err);
    }

#ifdef LDISC_RX_TASKLET
    tasklet_kill(&g_stp_uart_rx_fifo_tasklet);
    stp_uart_fifo_deinit();
#endif
    return;
}
static int mtk_wcn_stp_uart_init(void)
{
    static struct tty_ldisc_ops stp_uart_ldisc;
    int err;
	int fifo_init_done =0;

    UART_INFO_FUNC("mtk_wcn_stp_uart_init(): MTK STP UART driver\n");

#if  (LDISC_RX == LDISC_RX_TASKLET)
    err = stp_uart_fifo_init();
    if (err != 0)
    {
        goto init_err;
    }
	fifo_init_done = 1;
    /*init rx tasklet*/
    tasklet_init(&g_stp_uart_rx_fifo_tasklet, stp_uart_rx_handling, (unsigned long) 0);
	
#elif  (LDISC_RX == LDISC_RX_WORK)
	err = stp_uart_fifo_init();
	if (err != 0) {
		UART_ERR_FUNC("stp_uart_fifo_init(WORK) error(%d)\n", err);
		err = -EFAULT;
		goto init_err;
	}
	fifo_init_done = 1;

	g_stp_uart_rx_work = vmalloc(sizeof(struct work_struct));
	if (!g_stp_uart_rx_work) {
		UART_ERR_FUNC("vmalloc work_struct(%d) fail\n", sizeof(struct work_struct));
		err = -ENOMEM;
		goto init_err;
	}

	g_stp_uart_rx_wq = create_singlethread_workqueue("mtk_urxd");
	if (!g_stp_uart_rx_wq) {
		UART_ERR_FUNC("create_singlethread_workqueue fail\n");
		err = -ENOMEM;
		goto init_err;
	}

	/* init rx work */
	INIT_WORK(g_stp_uart_rx_work, stp_uart_rx_worker);

#endif

     /* Register the tty discipline */
    memset(&stp_uart_ldisc, 0, sizeof (stp_uart_ldisc));
    stp_uart_ldisc.magic    = TTY_LDISC_MAGIC;
    stp_uart_ldisc.name     = "n_mtkstp";
    stp_uart_ldisc.open     = stp_uart_tty_open;
    stp_uart_ldisc.close    = stp_uart_tty_close;
    stp_uart_ldisc.read     = stp_uart_tty_read;
    stp_uart_ldisc.write    = stp_uart_tty_write;
    stp_uart_ldisc.ioctl    = stp_uart_tty_ioctl;
    stp_uart_ldisc.poll     = stp_uart_tty_poll;
    stp_uart_ldisc.receive_buf  = stp_uart_tty_receive;
    stp_uart_ldisc.write_wakeup = stp_uart_tty_wakeup;
    stp_uart_ldisc.owner    = THIS_MODULE;

    if ((err = tty_register_ldisc(N_MTKSTP, &stp_uart_ldisc)))
    {
        UART_ERR_FUNC("MTK STP line discipline registration failed. (%d)\n", err);
        goto init_err;
    }

    /*
    mtk_wcn_stp_register_if_tx( mtk_wcn_uart_tx);
    */

    return 0;

init_err:
	
#if (LDISC_RX == LDISC_RX_TASKLET)
		/* nothing */
		if (fifo_init_done) {
			stp_uart_fifo_deinit();
		}
#elif (LDISC_RX == LDISC_RX_WORK)
		if (g_stp_uart_rx_wq) {
			destroy_workqueue(g_stp_uart_rx_wq);
			g_stp_uart_rx_wq = NULL;
		}
		if (g_stp_uart_rx_work) {
			vfree(g_stp_uart_rx_work);
		}
		if (fifo_init_done) {
			stp_uart_fifo_deinit();
		}
#endif
		UART_ERR_FUNC("init fail, return(%d)\n", err);
	
		return err;

}