예제 #1
0
static void stp_uart_rx_handling(unsigned long func_data){
    unsigned int how_much_get = 0;
    unsigned int how_much_to_get = 0;
    unsigned int flag = 0;
    
//    read_lock(&g_stp_uart_rx_handling_lock);
    how_much_to_get = kfifo_len(g_stp_uart_rx_fifo);
    
    if (how_much_to_get >= RX_BUFFER_LEN)
    {
        flag = 1;
        UART_INFO_FUNC ("fifolen(%d)\n", how_much_to_get);
    }
    
    do{
        #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
        how_much_get= kfifo_get(g_stp_uart_rx_fifo, g_rx_data, RX_BUFFER_LEN);
        #else
        how_much_get= kfifo_out(g_stp_uart_rx_fifo, g_rx_data, RX_BUFFER_LEN);
        #endif
        //UART_INFO_FUNC ("fifoget(%d)\n", how_much_get);
        mtk_wcn_stp_parser_data((UINT8 *)g_rx_data, how_much_get);
        how_much_to_get = kfifo_len(g_stp_uart_rx_fifo);
    }while(how_much_to_get > 0);
    
//    read_unlock(&g_stp_uart_rx_handling_lock);
    if (1 == flag)
    {
        UART_INFO_FUNC ("finish, fifolen(%d)\n", kfifo_len(g_stp_uart_rx_fifo));
    }
}
예제 #2
0
static void stp_uart_rx_handling(unsigned long func_data){
    #define LOCAL_BUFFER_LEN 1024
    unsigned char data[LOCAL_BUFFER_LEN];
    unsigned int how_much_get = 0;
    unsigned int how_much_to_get = 0;
    unsigned int flag = 0;

#if LDISC_RX_TASKLET_RWLOCK
    read_lock(&g_stp_uart_rx_handling_lock);
#endif

    how_much_to_get = kfifo_len(g_stp_uart_rx_fifo);

    if (how_much_to_get >= LOCAL_BUFFER_LEN)
    {
        flag = 1;
        UART_INFO_FUNC ("fifolen(%d)\n", how_much_to_get);
    }

    do {
        #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
        how_much_get= kfifo_get(g_stp_uart_rx_fifo, data, LOCAL_BUFFER_LEN);
        #else
        how_much_get= kfifo_out(g_stp_uart_rx_fifo, data, LOCAL_BUFFER_LEN);
        #endif
        UART_INFO_FUNC ("fifoget(%d)\n", how_much_get);
        mtk_wcn_stp_parser_data((UINT8 *)data, how_much_get);
        how_much_to_get = kfifo_len(g_stp_uart_rx_fifo);
    }while(how_much_to_get > 0);

#if LDISC_RX_TASKLET_RWLOCK
    read_unlock(&g_stp_uart_rx_handling_lock);
#endif

    if (1 == flag)
    {
        UART_INFO_FUNC ("finish, fifolen(%d)\n", kfifo_len(g_stp_uart_rx_fifo));
    }
}
예제 #3
0
static int __init mtk_wcn_stp_uart_init(void)
{
    static struct tty_ldisc_ops stp_uart_ldisc;
    int err;

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

#ifdef LDISC_RX_TASKLET
    err = stp_uart_fifo_init();
    if (err != 0)
    {
        return err;
    }
    /*init rx tasklet*/
    tasklet_init(&g_stp_uart_rx_fifo_tasklet, stp_uart_rx_handling, (unsigned long) 0);
#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);
        return err;
    }

    /*
    mtk_wcn_stp_register_if_tx( mtk_wcn_uart_tx);
    */

    return 0;
}
예제 #4
0
/* stp_uart_tty_ioctl()
 *
 *    Process IOCTL system call for the tty device.
 *
 * Arguments:
 *
 *    tty        pointer to tty instance data
 *    file       pointer to open file object for device
 *    cmd        IOCTL command code
 *    arg        argument for IOCTL call (cmd dependent)
 *
 * Return Value:    Command dependent
 */
static int stp_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
                    unsigned int cmd, unsigned long arg)
{
    int err = 0;

    UART_LOUD_FUNC("++ ll(%d)\n", tty->low_latency);

    switch (cmd) {
    case HCIUARTSETPROTO:
#if LDISC_LOW_LATENCY
        UART_INFO_FUNC("set low_latency to 1\n");
        tty->low_latency = 1;
#endif
        break;
    default:
        UART_LOUD_FUNC("redirect to n_tty_ioctl_helper\n");
        err = n_tty_ioctl_helper(tty, file, cmd, arg);
        UART_LOUD_FUNC("n_tty_ioctl_helper result(0x%x %d)\n", cmd, err);
        break;
    };

    UART_LOUD_FUNC("--\n");
    return err;
}
예제 #5
0
static inline int stp_uart_tx_wakeup(struct tty_struct *tty)
{
    int len = 0;
    int written = 0;
    int written_count = 0;
    static int i = 0;
    //unsigned long flags;
    // get data from ring buffer
//    down(&buf_mtx);
    UART_DBG_FUNC("++\n");
////    spin_lock_irqsave(&buf_lock, flags);

#if 0
    if((i > 1000) && (i % 5)== 0)
    {
        UART_INFO_FUNC("i=(%d), ****** drop data from uart******\n", i);
        i++;
        return 0;
    } else {

        UART_INFO_FUNC("i=(%d)at stp uart **\n", i);
    }
#endif

    len = (wr_idx >= rd_idx) ? (wr_idx - rd_idx) : (MTKSTP_BUFFER_SIZE - rd_idx);
    if(len > 0 && len < MAX_PACKET_ALLOWED)
    {
        i++;
        /*
         *     ops->write is called by the kernel to write a series of
         *     characters to the tty device.  The characters may come from
         *     user space or kernel space.  This routine will return the
         *    number of characters actually accepted for writing.
        */
        set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
        written = tty->ops->write(tty, &tx_buf[rd_idx], len);
        if(written != len) {
           UART_ERR_FUNC("Error(i-%d):[pid(%d)(%s)]tty-ops->write FAIL!len(%d)wr(%d)wr_i(%d)rd_i(%d)\n\r", i, current->pid, current->comm, len, written, wr_idx, rd_idx);
           return -1;
        }
        written_count = written;
        //printk("len = %d, written = %d\n", len, written);
        rd_idx = ((rd_idx + written) % MTKSTP_BUFFER_SIZE);
        // all data is accepted by UART driver, check again in case roll over
            len = (wr_idx >= rd_idx) ? (wr_idx - rd_idx) : (MTKSTP_BUFFER_SIZE - rd_idx);
            if(len > 0 && len < MAX_PACKET_ALLOWED)
            {
                set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
                written = tty->ops->write(tty, &tx_buf[rd_idx], len);
                if (written != len)
                {
                    UART_ERR_FUNC("Error(i-%d):[pid(%d)(%s)]len(%d)wr(%d)wr_i(%d)rd_i(%d)\n\r", i, current->pid, current->comm, len, written, wr_idx, rd_idx);
                    return -1;
                }
                rd_idx = ((rd_idx + written) % MTKSTP_BUFFER_SIZE);
                written_count += written;
            }
            else if(len < 0 || len >= MAX_PACKET_ALLOWED)
            {
                UART_ERR_FUNC("Warnning(i-%d):[pid(%d)(%s)]length verfication(external) warnning,len(%d), wr_idx(%d), rd_idx(%d)!\n\r", i, current->pid, current->comm, len, wr_idx, rd_idx);
                return -1;
            }
    }
    else
    {
        UART_ERR_FUNC("Warnning(i-%d):[pid(%d)(%s)]length verfication(external) warnning,len(%d), wr_idx(%d), rd_idx(%d)!\n\r", i, current->pid, current->comm, len, wr_idx, rd_idx);
        return -1;
    }
    //up(&buf_mtx);
////    spin_unlock_irqrestore(&buf_lock, flags);
    UART_DBG_FUNC("--\n");
    return written_count;
}
예제 #6
0
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;

}
예제 #7
0
static int stp_uart_fifo_init(void)
{
    int err = 0;

    #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
    g_stp_uart_rx_buf = vzalloc(LDISC_RX_BUF_SIZE);
    if (!g_stp_uart_rx_buf) {
        UART_ERR_FUNC("kfifo_alloc failed (kernel version >= 2.6.37)\n");
        err = -4;
        goto fifo_init_end;
    }
    #else
    g_stp_uart_rx_buf = vmalloc(LDISC_RX_BUF_SIZE);
    if (!g_stp_uart_rx_buf) {
        UART_ERR_FUNC("kfifo_alloc failed (kernel version < 2.6.37)\n");
        err = -4;
        goto fifo_init_end;
    }
    memset(g_stp_uart_rx_buf, 0, LDISC_RX_BUF_SIZE);
    #endif

    UART_INFO_FUNC("g_stp_uart_rx_buf alloc ok(0x%p, %d)\n",
        g_stp_uart_rx_buf, LDISC_RX_BUF_SIZE);

    /*add rx fifo*/
    #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
    spin_lock_init(&g_stp_uart_rx_fifo_spinlock);
    g_stp_uart_rx_fifo = kfifo_alloc(LDISC_RX_FIFO_SIZE, GFP_KERNEL, &g_stp_uart_rx_fifo_spinlock);
    if (NULL == g_stp_uart_rx_fifo) {
        UART_ERR_FUNC("kfifo_alloc failed (kernel version < 2.6.33)\n");
        err = -1;
        goto fifo_init_end;
    }
    #else
    /* allocate struct kfifo first */
    g_stp_uart_rx_fifo = kzalloc(sizeof(struct kfifo), GFP_KERNEL);
    if (NULL == g_stp_uart_rx_fifo) {
        err = -2;
        UART_ERR_FUNC("kzalloc struct kfifo failed (kernel version > 2.6.33)\n");
        goto fifo_init_end;
    }

    /* allocate kfifo data buffer then */
    err = kfifo_alloc(g_stp_uart_rx_fifo, LDISC_RX_FIFO_SIZE, GFP_KERNEL);
    if (0 != err) {
        UART_ERR_FUNC("kfifo_alloc failed, err(%d)(kernel version > 2.6.33)\n", err);
        kfree(g_stp_uart_rx_fifo);
        g_stp_uart_rx_fifo = NULL;
        err = -3;
        goto fifo_init_end;
    }
    #endif
    UART_INFO_FUNC("g_stp_uart_rx_fifo alloc ok\n");

fifo_init_end:

    if (0 == err) {
        /* kfifo init ok */
        kfifo_reset(g_stp_uart_rx_fifo);
        UART_DBG_FUNC("g_stp_uart_rx_fifo init success\n");
    }
    else {
        UART_ERR_FUNC("stp_uart_fifo_init() fail(%d)\n", err);
        if (g_stp_uart_rx_buf) {
            UART_ERR_FUNC("free g_stp_uart_rx_buf\n");
            vfree(g_stp_uart_rx_buf);
            g_stp_uart_rx_buf = NULL;
        }
    }

    return err;
}
예제 #8
0
static INT32 mtk_wcn_uart_tx (
    const UINT8 *data,
    const UINT32 size,
    UINT32 *written_size
    )
{
    INT32 ret;
    int tx_len;

    if (unlikely(0 == size)) {
        /* special case for STP-CORE, return ASAP. */
        if (likely(written_size)) {
            *written_size = 0;
        }
        return 0;
    }

    UART_LOUD_FUNC("++\n");

    /* input sanity checks */
    if (unlikely(stp_tty == NULL)) {
        UART_ERR_FUNC("NULL stp_tty,pid[%d/%s]\n", current->pid, current->comm);
        ret = -1;
        goto uart_tx_out;
    }

    if (unlikely((data == NULL) || (written_size == NULL))) {
        UART_ERR_FUNC("NULL data(0x%p) or written(0x%p),pid[%d/%s]\n",
            data, written_size, current->pid, current->comm);
        ret = -2;
        goto uart_tx_out;
    }

    *written_size = 0;

    /* Do size checking. Only 1~MAX_PACKET_ALLOWED-1 is allowed */
    if (unlikely(MAX_PACKET_ALLOWED <= size)) {
        UART_ERR_FUNC("abnormal size(%d),skip tx,pid[%d/%s]\n",
            size, current->pid, current->comm);
        dump_stack();
        ret = -3;
        goto uart_tx_out;
    }

#if 0 /* drop data test */
    if ((tx_count > 1000) && (tx_count % 5)== 0) {
        UART_INFO_FUNC("i=(%d), ****** drop data from uart******\n", i);
        ++tx_count;
        return 0;
    }
#endif

    tx_len = stp_uart_tty_tx_write(stp_tty, data, size);
    if (unlikely(tx_len < 0)) {
        UART_WARN_FUNC("stp_uart_tty_tx_write err(%d)\n", tx_len);
        *written_size = 0;
        ret = -4;
    }
    else {
        *written_size = tx_len;
        ret = 0;
    }

uart_tx_out:
    UART_LOUD_FUNC("--(%d, %d)\n", ret, *written_size);

    return ret;
}