/* stp_uart_tty_receive()
 *
 *     Called by tty low level driver when receive data is
 *     available.
 *
 * Arguments:  tty          pointer to tty isntance data
 *             data         pointer to received data
 *             flags        pointer to flags for data
 *             count        count of received data in bytes
 *
 * Return Value:    None
 */
static void stp_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
{
    unsigned int written;

    //UART_LOUD_FUNC("URX:%d\n", count);
    if (unlikely(count > 2000)) {
        UART_WARN_FUNC("abnormal: buffer count = %d\n", count);
    }

    if (unlikely(!g_stp_uart_rx_fifo || !g_stp_uart_rx_work || !g_stp_uart_rx_wq)) {
        UART_ERR_FUNC("abnormal g_stp_uart_rx_fifo(0x%p),g_stp_uart_rx_work(0x%p),g_stp_uart_rx_wq(0x%p)\n",
            g_stp_uart_rx_fifo, g_stp_uart_rx_work, g_stp_uart_rx_wq);
        return;
    }

    /* need to check available buffer size? skip! */

    /* need to lock fifo? skip for single writer single reader! */

#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
    written = kfifo_put(g_stp_uart_rx_fifo, (unsigned char *) data, count);
#else
    written = kfifo_in(g_stp_uart_rx_fifo, (unsigned char *) data, count);
#endif
	//printk("uart_rx:%d,wr:%d\n\r",count,written);

    queue_work(g_stp_uart_rx_wq, g_stp_uart_rx_work);

    if (unlikely(written != count)) {
        UART_ERR_FUNC("c(%d),w(%d) bytes dropped\n", count, written);
    }

    return;
}
Esempio n. 2
0
/* stp_uart_tty_receive()
 *
 *     Called by tty low level driver when receive data is
 *     available.
 *
 * Arguments:  tty          pointer to tty isntance data
 *             data         pointer to received data
 *             flags        pointer to flags for data
 *             count        count of received data in bytes
 *
 * Return Value:    None
 */
static void stp_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
{
    //UART_INFO_FUNC("count = %d\n", count);

    if (count > 2000){
        /*this is abnormal*/
        UART_WARN_FUNC("count = %d\n", count);
    }

#if 0
    {
        struct timeval now;

        do_gettimeofday(&now);

        printk("[+STP][  ][R] %4d --> sec = %d, --> usec --> %d\n",
            count, now.tv_sec, now.tv_usec);
    }
#endif


    /*There are multi-context to access here? Need to spinlock?*/
    /*Only one context: flush_to_ldisc in tty_buffer.c*/
    mtk_wcn_stp_parser_data((UINT8 *)data, (UINT32)count);

    /* George Test: useless? */
    /*tty_unthrottle(tty);*/

#if 0
    {
        struct timeval now;

        do_gettimeofday(&now);

        printk("[-STP][  ][R] %4d --> sec = %d, --> usec --> %d\n",
            count, now.tv_sec, now.tv_usec);
    }
#endif
    return;
}
Esempio n. 3
0
/* stp_uart_tty_open
 *
 * Arguments:
 *     tty  pointer to tty info structure
 *     data pointer to data buffer to be written
 *     size data buffer length to be written
 * Return Value:
 *     > 0 if success, otherwise error code
 */
static int stp_uart_tty_tx_write (
    struct tty_struct *tty,
    const UINT8 *data,
    const UINT32 size
    )
{
    int ret;
    int len;
    int written;
    int written_count;
    int room;
    unsigned old_wr;
    unsigned old_rd;
    //unsigned long flags;

    UART_LOUD_FUNC("++\n");

    /* Phase-I: put data into STP-UART ring buffer "tx_buf" */
    /* wr_idx : the position next to write
     *  rd_idx : the position next to read
     */

    //down(&buf_mtx);
    /* [PatchNeed] spin_lock_irqsave is redundant */
    //spin_lock_irqsave(&buf_lock, flags);
    old_wr = wr_idx;
    old_rd = rd_idx;

    /* check left room size */
    room = (wr_idx >= rd_idx)
        ? (STP_UART_TX_BUF_SIZE - (wr_idx - rd_idx) - 1)
        : (rd_idx - wr_idx - 1);
    UART_DBG_FUNC("before data in:r(%d)s(%d)wr_i(%d)rd_i(%d)\n",
        room, size, wr_idx, rd_idx);

    if (unlikely(size > room)) {
        UART_ERR_FUNC("buf unavailable FAIL#1,size(%d),wr_idx(%d),rd_idx(%d),room(%d),pid[%d/%s]\n",
            size, wr_idx, rd_idx, room, current->pid, current->comm);
        //up(&buf_mtx);
        /* [PatchNeed] spin_lock_irqsave is redundant */
        //spin_unlock_irqrestore(&buf_lock, flags);
        return -1;
    }
    else {
        len = min(size, STP_UART_TX_BUF_SIZE - (unsigned int)wr_idx);
        memcpy(&tx_buf[wr_idx], &data[0], len);
        memcpy(&tx_buf[0], &data[len], size - len);
        wr_idx = (wr_idx + size) % STP_UART_TX_BUF_SIZE;
        UART_DBG_FUNC("after data in: r(%d)s(%d)wr_i(%d)rd_i(%d)\n",
            room, size, wr_idx, rd_idx);
    }
    //up(&buf_mtx);
    /* [PatchNeed] spin_lock_irqsave is redundant */
    //spin_unlock_irqrestore(&buf_lock, flags);

    /* Phase-II: get data from the buffer and send to tty UART.
     * May be seperated into another context.
    */

    //down(&buf_mtx);
    /* [PatchNeed] spin_lock_irqsave is redundant */
    //spin_lock_irqsave(&buf_lock, flags);
    written_count = 0;

    len = (wr_idx >= rd_idx) ? (wr_idx - rd_idx) : (STP_UART_TX_BUF_SIZE - rd_idx);
    if (likely(len > 0 && len < MAX_PACKET_ALLOWED))
    {
        /* TTY_DO_WRITE_WAKEUP is used for "Call write_wakeup after queuing new"
         * but stp_uart_tty_wakeup() is empty and unused now!
         */
        //set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);

        /*
         * 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.
        */
        written = tty->ops->write(tty, &tx_buf[rd_idx], len);
        if (written != len) {
            UART_ERR_FUNC("tty-ops->write FAIL#2,len(%d)wr(%d)wr_i(%d)rd_i(%d),pid[%d/%s]\n",
                len, written, wr_idx, rd_idx, current->pid, current->comm);
            ret = -2;
            goto tx_write_out_unlock_old;
        }
        written_count = written;
        rd_idx = ((rd_idx + written) % STP_UART_TX_BUF_SIZE);

        // all data is accepted by UART driver, check again in case roll over
        len = (wr_idx >= rd_idx) ? (wr_idx - rd_idx) : (STP_UART_TX_BUF_SIZE - rd_idx);
        if (len > 0 && len < MAX_PACKET_ALLOWED)
        {
            /* TTY_DO_WRITE_WAKEUP is used for "Call write_wakeup after queuing new"
             * but stp_uart_tty_wakeup() is empty and unused now!
             */
            //set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);

            written = tty->ops->write(tty, &tx_buf[rd_idx], len);
            if (unlikely(written != len))
            {
                UART_ERR_FUNC("tty-ops->write FAIL#3,len(%d)wr(%d)wr_i(%d)rd_i(%d),pid[%d/%s]\n",
                    len, written, wr_idx, rd_idx, current->pid, current->comm);
                ret = -3;
                goto tx_write_out_unlock_old;
            }
            rd_idx = ((rd_idx + written) % STP_UART_TX_BUF_SIZE);
            written_count += written;
        }
        else if (unlikely(len < 0 || len >= MAX_PACKET_ALLOWED))
        {
            UART_ERR_FUNC("FAIL#4,len(%d)wr_i(%d)rd_i(%d),pid[%d/%s]\n",
                len, wr_idx, rd_idx,
                current->pid, current->comm);
            ret = -4;
            goto tx_write_out_unlock_old;
        }
    }
    else
    {
        UART_ERR_FUNC("FAIL#5,len(%d)wr_i(%d)rd_i(%d),pid[%d/%s]\n",
            len, wr_idx, rd_idx,
            current->pid, current->comm);
        ret = -5;
        goto tx_write_out_unlock_old;
    }

    /* success case */
    ret = written_count;


tx_write_out_unlock_old:
    if (unlikely(ret < 0)) {
        //reset read and write index of tx_buffer, is there any risk?
        wr_idx = rd_idx = 0;
        UART_ERR_FUNC("err(%d)reset fifo idx\n", ret);
    }

    if (unlikely(wr_idx != rd_idx)) {
        UART_WARN_FUNC("--wr(%d)rd(%d)size(%d)old wr(%d)rd(%d)\n",
            wr_idx, rd_idx, size, old_wr, old_rd);

   }
    else {
        UART_LOUD_FUNC("--wr(%d) rd(%d)\n", wr_idx, rd_idx);
    }
    //up(&buf_mtx);
    //spin_unlock_irqrestore(&buf_lock, flags);

    return ret;
}
Esempio n. 4
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;
}