public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] USB: cdc-acm: Prevent data loss when filling tty buffer.
@ 2011-03-21 15:52 Toby Gray
  2011-03-21 16:56 ` Alan Cox
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Toby Gray @ 2011-03-21 15:52 UTC (permalink / raw)
  To: Oliver Neukum, Greg Kroah-Hartman, linux-usb; +Cc: linux-kernel, Toby Gray

When sending large quantities of data through a CDC ACM channel it is possible
for data to be lost when attempting to copy the data to the tty buffer. This
occurs due to the return value from tty_insert_flip_string not being checked.

This patch adds checking for how many bytes have been inserted into the tty
buffer and returns any remaining bytes back to the filled read buffer list.

Signed-off-by: Toby Gray <toby.gray@realvnc.com>
---
 drivers/usb/class/cdc-acm.c |   28 ++++++++++++++++++++++++----
 1 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index f492a7f..63133c7 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -392,6 +392,7 @@ static void acm_rx_tasklet(unsigned long _acm)
 	struct acm_ru *rcv;
 	unsigned long flags;
 	unsigned char throttled;
+	int copied;
 
 	dbg("Entering acm_rx_tasklet");
 
@@ -423,12 +424,14 @@ next_buffer:
 
 	dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size);
 
+	copied = 0;
 	if (tty) {
 		spin_lock_irqsave(&acm->throttle_lock, flags);
 		throttled = acm->throttle;
 		spin_unlock_irqrestore(&acm->throttle_lock, flags);
 		if (!throttled) {
-			tty_insert_flip_string(tty, buf->base, buf->size);
+			copied = tty_insert_flip_string(tty,
+							buf->base, buf->size);
 			tty_flip_buffer_push(tty);
 		} else {
 			tty_kref_put(tty);
@@ -440,9 +443,26 @@ next_buffer:
 		}
 	}
 
-	spin_lock_irqsave(&acm->read_lock, flags);
-	list_add(&buf->list, &acm->spare_read_bufs);
-	spin_unlock_irqrestore(&acm->read_lock, flags);
+	if (copied == buf->size || !tty) {
+		spin_lock_irqsave(&acm->read_lock, flags);
+		list_add(&buf->list, &acm->spare_read_bufs);
+		spin_unlock_irqrestore(&acm->read_lock, flags);
+	} else {
+		tty_kref_put(tty);
+		dbg("Partial buffer fill");
+		if (copied > 0) {
+			memmove(buf->base,
+				buf->base + copied,
+				buf->size - copied);
+			buf->size -= copied;
+		}
+
+		spin_lock_irqsave(&acm->read_lock, flags);
+		list_add(&buf->list, &acm->filled_read_bufs);
+		spin_unlock_irqrestore(&acm->read_lock, flags);
+		return;
+	}
+
 	goto next_buffer;
 
 urbs:
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2011-03-23 12:15 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-21 15:52 [PATCH] USB: cdc-acm: Prevent data loss when filling tty buffer Toby Gray
2011-03-21 16:56 ` Alan Cox
2011-03-21 17:58   ` Toby Gray
2011-03-22  8:07   ` Oliver Neukum
2011-03-22 11:07     ` Alan Cox
2011-03-21 18:04 ` [PATCH v2] " Toby Gray
2011-03-22 10:05   ` Johan Hovold
2011-03-22 10:35     ` Alan Cox
2011-03-22 11:34       ` Johan Hovold
2011-03-22 14:11     ` Toby Gray
2011-03-22 18:05       ` Alan Cox
2011-03-22  7:43 ` [PATCH] " Oliver Neukum
2011-03-23 12:15   ` Toby Gray

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox