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; }
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; }