patch-2.4.5 linux/drivers/char/serial167.c

Next file: linux/drivers/char/softdog.c
Previous file: linux/drivers/char/serial.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.4/linux/drivers/char/serial167.c linux/drivers/char/serial167.c
@@ -1247,36 +1247,54 @@
         return 0;
     }
 
-    while (1) {
-        save_flags(flags); cli();		
-	c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-			   SERIAL_XMIT_SIZE - info->xmit_head));
-	if (c <= 0){
-	    restore_flags(flags);
-	    break;
-	}
-
-	if (from_user) {
+    if (from_user) {
 	    down(&tmp_buf_sem);
-	    if (copy_from_user(tmp_buf, buf, c)) {
-	    	up(&tmp_buf_sem);
-	        restore_flags(flags);
-		return 0;
+	    while (1) {
+		    c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				       SERIAL_XMIT_SIZE - info->xmit_head));
+		    if (c <= 0)
+			    break;
+
+		    c -= copy_from_user(tmp_buf, buf, c);
+		    if (!c) {
+			    if (!total)
+				    total = -EFAULT;
+			    break;
+		    }
+
+		    cli();
+		    c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				   SERIAL_XMIT_SIZE - info->xmit_head));
+		    memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
+		    info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+		    info->xmit_cnt += c;
+		    restore_flags(flags);
+
+		    buf += c;
+		    count -= c;
+		    total += c;
 	    }
-	    c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-		       SERIAL_XMIT_SIZE - info->xmit_head));
-	    memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
 	    up(&tmp_buf_sem);
-	} else
-	    memcpy(info->xmit_buf + info->xmit_head, buf, c);
-	info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-	info->xmit_cnt += c;
-	restore_flags(flags);
-	buf += c;
-	count -= c;
-	total += c;
-    }
+    } else {
+	    while (1) {
+		    cli();
+		    c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				       SERIAL_XMIT_SIZE - info->xmit_head));
+		    if (c <= 0) {
+			    restore_flags(flags);
+			    break;
+		    }
+
+		    memcpy(info->xmit_buf + info->xmit_head, buf, c);
+		    info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+		    info->xmit_cnt += c;
+		    restore_flags(flags);
 
+		    buf += c;
+		    count -= c;
+		    total += c;
+	    }
+    }
 
     if (info->xmit_cnt
     && !tty->stopped

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)