Index: linux-2.6.16/drivers/char/ts0710_mux_usb.c =================================================================== --- linux-2.6.16.orig/drivers/char/ts0710_mux_usb.c 2007-01-17 00:52:25.000000000 +0100 +++ linux-2.6.16/drivers/char/ts0710_mux_usb.c 2007-01-17 00:52:26.000000000 +0100 @@ -133,6 +133,7 @@ struct circ_buf xmit; /* write cric bufffer */ struct list_head in_buf_list; + spinlock_t in_buf_lock; char bulk_in_ep_mux, bulk_out_ep_mux, bulk_in_ep_dsplog; @@ -204,9 +205,39 @@ return; } memcpy(inbuf->body, (unsigned char*)urb->transfer_buffer, count); + spin_lock(&bvd_ipc->in_buf_lock); list_add_tail(&inbuf->list, &bvd_ipc->in_buf_list); + spin_unlock(&bvd_ipc->in_buf_lock); } +int get_from_inbuf_list(const unsigned char *buf, int dst_count) +{ + int ret = 0; + spin_lock(&bvd_ipc->in_buf_lock); + if (!(list_empty(&bvd_ipc->in_buf_list))) { + int src_count; + buf_list_t *inbuf; + struct list_head *ptr; + + ptr = bvd_ipc->in_buf_list.next; + inbuf = list_entry(ptr, buf_list_t, list); + src_count = inbuf->size; + if (dst_count >= src_count) { + memcpy(buf, inbuf->body, src_count); + ret = src_count; + list_del(ptr); + kfree(inbuf->body); + kfree(inbuf); + } else { + bvd_dbg("get_from_inbuf_list: not enough space in destination buffer"); + } + } + spin_unlock(&bvd_ipc->in_buf_lock); + + return ret; +} +EXPORT_SYMBOL(get_from_inbuf_list); + static void ipcusb_timeout(unsigned long data) { struct tty_struct *tty = &ipcusb_tty; @@ -214,13 +245,14 @@ bvd_dbg("ipcusb_timeout***"); + spin_lock(&bvd_ipc->in_buf_lock); while (!(list_empty(&bvd_ipc->in_buf_list))) { int count; buf_list_t *inbuf; struct list_head *ptr = NULL; ptr = bvd_ipc->in_buf_list.next; - inbuf = list_entry (ptr, buf_list_t, list); + inbuf = list_entry(ptr, buf_list_t, list); count = inbuf->size; if (tty_insert_flip_string(tty, inbuf->body, count) >= count) { list_del(ptr); @@ -232,10 +264,12 @@ break; } } + spin_unlock(&bvd_ipc->in_buf_lock); if (usb_mux_dispatcher) usb_mux_dispatcher(tty); /**call Liu changhui's func.**/ + spin_lock(&bvd_ipc->in_buf_lock); if (list_empty(&bvd_ipc->in_buf_list)) { urb->actual_length = 0; urb->dev = bvd_ipc->ipc_dev; @@ -246,6 +280,7 @@ ipcusb_timer.data = (unsigned long)urb; mod_timer(&ipcusb_timer, jiffies+(10*HZ/1000)); } + spin_unlock(&bvd_ipc->in_buf_lock); } static void usb_ipc_read_bulk(struct urb *urb, struct pt_regs *regs) @@ -266,69 +301,11 @@ if (count > 0 && ((*ipcusb_bp_to_ap) != NULL)) (*ipcusb_bp_to_ap)(urb->transfer_buffer, urb->actual_length); - if (!(list_empty(&bvd_ipc->in_buf_list))) { - int need_mux = 0; - - bvd_dbg("usb_ipc_read_bulk: some urbs in_buf_list"); - if (count > 0) { - bvd_ipc->suspend_flag = 1; - append_to_inbuf_list(urb); /* append the current received urb */ -#if 0 - if(jiffies - last_jiff > ICL_EVENT_INTERVAL) - { - last_jiff = jiffies; - queue_apm_event(KRNL_ICL, NULL); - } -#endif - } - - while (!(list_empty(&bvd_ipc->in_buf_list))) { - struct list_head* ptr = NULL; - ptr = bvd_ipc->in_buf_list.next; - inbuf = list_entry(ptr, buf_list_t, list); - count = inbuf->size; - need_mux = 1; - - tty_insert_flip_string(tty, inbuf->body, count); - - list_del(ptr); - kfree(inbuf->body); - inbuf->body = NULL; - kfree(inbuf); - } - - if (usb_mux_dispatcher && need_mux) - usb_mux_dispatcher(tty); /* call Liu changhui's func. */ - - if (list_empty(&bvd_ipc->in_buf_list)) { - urb->actual_length = 0; - urb->dev = bvd_ipc->ipc_dev; - if (usb_submit_urb(urb, GFP_ATOMIC)) - bvd_dbg("usb_ipc_read_bulk: " - "failed resubmitting read urb"); - bvd_dbg("usb_ipc_read_bulk: resubmited read urb"); - } else { - ipcusb_timer.data = (unsigned long)urb; - mod_timer(&ipcusb_timer, jiffies+(10*HZ/1000)); - } - } else if (count > 0) { - bvd_dbg("usb_ipc_read_bulk: no urbs in_buf_list"); + if (count > 0) { + bvd_dbg("usb_ipc_read_bulk: inserting buffer into in_buf_list"); bvd_ipc->suspend_flag = 1; - if (tty_insert_flip_string(tty, urb->transfer_buffer, - count) < count) { - bvd_ipc->suspend_flag = 1; - append_to_inbuf_list(urb); - ipcusb_timer.data = (unsigned long)urb; - mod_timer(&ipcusb_timer, jiffies+(10*HZ/1000)); -#if 0 - if(jiffies - last_jiff > ICL_EVENT_INTERVAL) - { - last_jiff = jiffies; - queue_apm_event(KRNL_ICL, NULL); - } -#endif - } + append_to_inbuf_list(urb); if (usb_mux_dispatcher) usb_mux_dispatcher(tty); /* call Liu changhui's func. */ @@ -337,13 +314,6 @@ urb->dev = bvd_ipc->ipc_dev; if (usb_submit_urb(urb, GFP_ATOMIC)) bvd_dbg("failed resubmitting read urb"); -#if 0 - if(jiffies - last_jiff > ICL_EVENT_INTERVAL) - { - last_jiff = jiffies; - queue_apm_event(KRNL_ICL, NULL); - } -#endif bvd_dbg("usb_ipc_read_bulk: resubmited read urb"); } @@ -705,7 +675,8 @@ bvd_ipc->bulk_out_ep_mux= have_bulk_out_mux; bvd_ipc->ipc_dev = usbdev; bvd_ipc->writesize = writesize; - INIT_LIST_HEAD (&bvd_ipc->in_buf_list); + INIT_LIST_HEAD(&bvd_ipc->in_buf_list); + bvd_ipc->in_buf_lock = SPIN_LOCK_UNLOCKED; bvd_ipc->bh.func = usbipc_bh_func; bvd_ipc->bh.data = (unsigned long) bvd_ipc; Index: linux-2.6.16/drivers/char/ts0710_mux.c =================================================================== --- linux-2.6.16.orig/drivers/char/ts0710_mux.c 2007-01-17 00:52:23.000000000 +0100 +++ linux-2.6.16/drivers/char/ts0710_mux.c 2007-01-17 00:52:26.000000000 +0100 @@ -3149,7 +3149,7 @@ static void receive_worker(void *private_) { struct tty_struct *tty = COMM_FOR_MUX_TTY; - int i, count; + int i, count, tbuf_free, tbuf_read; static unsigned char tbuf[TS0710MUX_MAX_BUF_SIZE]; static unsigned char *tbuf_ptr = &tbuf[0]; static unsigned char *start_flag = 0; @@ -3167,29 +3167,39 @@ UNUSED_PARAM(private_); - if (!tty) - return; + if (!tty) + return; + + while (1) { + tbuf_free = TS0710MUX_MAX_BUF_SIZE - (tbuf_ptr - tbuf); + TS0710_PRINTK("Reading max %i bytes from ts0710_mux_usb inbuf.\n", tbuf_free); + tbuf_read = get_from_inbuf_list(tbuf_ptr, tbuf_free); + if (tbuf_read == 0) { + break; + } else { + TS0710_PRINTK("Read %i bytes.\n", tbuf_read); + }; + tbuf_ptr += tbuf_read; + }; + + count = (tbuf_ptr - tbuf); + + // Should be impossible? + //if (count > (TS0710MUX_MAX_BUF_SIZE - (tbuf_ptr - tbuf))) { + // TS0710_PRINTK + // ("MUX receive_worker: !!!!! Exceed buffer boundary !!!!!\n"); + // count = (TS0710MUX_MAX_BUF_SIZE - (tbuf_ptr - tbuf)); + //} #ifdef USB_FOR_MUX - TS0710_DEBUG("Receive following bytes from IPC-USB"); + TS0710_DEBUG("Received following bytes from IPC-USB"); #else - TS0710_DEBUG("Receive following bytes from UART"); + TS0710_DEBUG("Received following bytes from UART"); #endif - - TS0710_DEBUGHEX(cp, count); - - if (count > (TS0710MUX_MAX_BUF_SIZE - (tbuf_ptr - tbuf))) { - TS0710_PRINTK - ("MUX receive_worker: !!!!! Exceed buffer boundary !!!!!\n"); - count = (TS0710MUX_MAX_BUF_SIZE - (tbuf_ptr - tbuf)); - } - - count = tty_buffer_request_room(tty, count); - - for (i = 0; i < count; i++) - tty_insert_flip_char(tty, tbuf_ptr[i], TTY_NORMAL); - - tbuf_ptr += count; + TS0710_DEBUGHEX(tbuf, count); + + //gets updated above + //tbuf_ptr += count; search = &tbuf[0]; if (test_and_set_bit(RECV_RUNNING, &mux_recv_flags)) { Index: linux-2.6.16/drivers/char/ts0710_mux_usb.h =================================================================== --- linux-2.6.16.orig/drivers/char/ts0710_mux_usb.h 2007-01-17 00:52:23.000000000 +0100 +++ linux-2.6.16/drivers/char/ts0710_mux_usb.h 2007-01-17 00:52:26.000000000 +0100 @@ -27,3 +27,6 @@ extern struct tty_struct *usb_for_mux_tty; extern void (*usb_mux_dispatcher)(struct tty_struct *tty); extern void (*usb_mux_sender)(void); + +extern int get_from_inbuf_list(const unsigned char *buf, int dst_count); +