mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] s390 (8/8): console driver fixes.
@ 2003-10-21 15:10 Martin Schwidefsky
  0 siblings, 0 replies; only message in thread
From: Martin Schwidefsky @ 2003-10-21 15:10 UTC (permalink / raw)
  To: torvalds, linux-kernel

Move copy_from_user out of locked code in the 3215 and sclp driver.

diffstat:
 drivers/s390/char/con3215.c  |   88 ++++++++++++++++++-------------------------
 drivers/s390/char/sclp_con.c |    4 -
 drivers/s390/char/sclp_rw.c  |   16 +------
 drivers/s390/char/sclp_rw.h  |    2 
 drivers/s390/char/sclp_tty.c |   38 ++++++++++++++----
 5 files changed, 73 insertions(+), 75 deletions(-)

diff -urN linux-2.6/drivers/s390/char/con3215.c linux-2.6-s390/drivers/s390/char/con3215.c
--- linux-2.6/drivers/s390/char/con3215.c	Fri Oct 17 23:43:20 2003
+++ linux-2.6-s390/drivers/s390/char/con3215.c	Tue Oct 21 16:37:39 2003
@@ -96,6 +96,7 @@
 	int msg_dstat;		      /* dstat for pending message */
 	int msg_cstat;		      /* cstat for pending message */
 	int line_pos;		      /* position on the line (for tabs) */
+	char ubuffer[80];	      /* copy_from_user buffer */
 };
 
 /* array of 3215 devices structures */
@@ -532,15 +533,12 @@
 /*
  * String write routine for 3215 devices
  */
-static int
-raw3215_write(struct raw3215_info *raw, const char *str,
-	      int from_user, unsigned int length)
+static void
+raw3215_write(struct raw3215_info *raw, const char *str, unsigned int length)
 {
 	unsigned long flags;
-	int ret, c;
-	int count;
+	int c, count;
 
-	ret = 0;
 	while (length > 0) {
 		spin_lock_irqsave(raw->lock, flags);
 		count = (length > RAW3215_BUFFER_SIZE) ?
@@ -550,46 +548,19 @@
 		raw3215_make_room(raw, count);
 
 		/* copy string to output buffer and convert it to EBCDIC */
-		if (from_user) {
-			while (1) {
-				c = min_t(int, count,
-					min(RAW3215_BUFFER_SIZE - raw->count,
-					    RAW3215_BUFFER_SIZE - raw->head));
-				if (c <= 0)
-					break;
-				c -= copy_from_user(raw->buffer + raw->head,
-						    str, c);
-				if (c == 0) {
-					if (!ret)
-						ret = -EFAULT;
-					break;
-				}
-				ASCEBC(raw->buffer + raw->head, c);
-				raw->head = (raw->head + c) &
-					    (RAW3215_BUFFER_SIZE - 1);
-				raw->count += c;
-				raw->line_pos += c;
-				str += c;
-				count -= c;
-				ret += c;
-			}
-		} else {
-			while (1) {
-				c = min_t(int, count,
-					min(RAW3215_BUFFER_SIZE - raw->count,
-					    RAW3215_BUFFER_SIZE - raw->head));
-				if (c <= 0)
-					break;
-				memcpy(raw->buffer + raw->head, str, c);
-				ASCEBC(raw->buffer + raw->head, c);
-				raw->head = (raw->head + c) &
-					    (RAW3215_BUFFER_SIZE - 1);
-				raw->count += c;
-				raw->line_pos += c;
-				str += c;
-				count -= c;
-				ret += c;
-			}
+		while (1) {
+			c = min_t(int, count,
+				  min(RAW3215_BUFFER_SIZE - raw->count,
+				      RAW3215_BUFFER_SIZE - raw->head));
+			if (c <= 0)
+				break;
+			memcpy(raw->buffer + raw->head, str, c);
+			ASCEBC(raw->buffer + raw->head, c);
+			raw->head = (raw->head + c) & (RAW3215_BUFFER_SIZE - 1);
+			raw->count += c;
+			raw->line_pos += c;
+			str += c;
+			count -= c;
 		}
 		if (!(raw->flags & RAW3215_WORKING)) {
 			raw3215_mk_write_req(raw);
@@ -598,8 +569,6 @@
 		}
 		spin_unlock_irqrestore(raw->lock, flags);
 	}
-
-	return ret;
 }
 
 /*
@@ -825,7 +794,7 @@
 		for (i = 0; i < count; i++)
 			if (str[i] == '\t' || str[i] == '\n')
 				break;
-		raw3215_write(raw, str, 0, i);
+		raw3215_write(raw, str, i);
 		count -= i;
 		str += i;
 		if (count > 0) {
@@ -1021,12 +990,29 @@
 	      const unsigned char *buf, int count)
 {
 	struct raw3215_info *raw;
-	int ret = 0;
+	int length, ret;
 
 	if (!tty)
 		return 0;
 	raw = (struct raw3215_info *) tty->driver_data;
-	ret = raw3215_write(raw, buf, from_user, count);
+	if (!from_user) {
+		raw3215_write(raw, buf, count);
+		return count;
+	}
+	ret = 0;
+	while (count > 0) {
+		length = count < 80 ? count : 80;
+		length -= copy_from_user(raw->ubuffer, buf, length);
+		if (length == 0) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
+		raw3215_write(raw, raw->ubuffer, count);
+		buf += length;
+		count -= length;
+		ret += length;
+	}
 	return ret;
 }
 
diff -urN linux-2.6/drivers/s390/char/sclp_con.c linux-2.6-s390/drivers/s390/char/sclp_con.c
--- linux-2.6/drivers/s390/char/sclp_con.c	Fri Oct 17 23:43:12 2003
+++ linux-2.6-s390/drivers/s390/char/sclp_con.c	Tue Oct 21 16:37:39 2003
@@ -134,8 +134,8 @@
 		}
 		/* try to write the string to the current output buffer */
 		written = sclp_write(sclp_conbuf, (const unsigned char *)
-				     message, count, 0);
-		if (written == -EFAULT || written == count)
+				     message, count);
+		if (written == count)
 			break;
 		/*
 		 * Not all characters could be written to the current
diff -urN linux-2.6/drivers/s390/char/sclp_rw.c linux-2.6-s390/drivers/s390/char/sclp_rw.c
--- linux-2.6/drivers/s390/char/sclp_rw.c	Fri Oct 17 23:43:10 2003
+++ linux-2.6-s390/drivers/s390/char/sclp_rw.c	Tue Oct 21 16:37:39 2003
@@ -175,11 +175,9 @@
  *  is not busy)
  */
 int
-sclp_write(struct sclp_buffer *buffer,
-	   const unsigned char *msg, int count, int from_user)
+sclp_write(struct sclp_buffer *buffer, const unsigned char *msg, int count)
 {
 	int spaces, i_msg;
-	char ch;
 	int rc;
 
 	/*
@@ -206,13 +204,7 @@
 	 * This is in order to a slim and quick implementation.
 	 */
 	for (i_msg = 0; i_msg < count; i_msg++) {
-		if (from_user) {
-			if (get_user(ch, msg + i_msg) != 0)
-				return -EFAULT;
-		} else
-			ch = msg[i_msg];
-
-		switch (ch) {
+		switch (msg[i_msg]) {
 		case '\n':	/* new line, line feed (ASCII)	*/
 			/* check if new mto needs to be created */
 			if (buffer->current_line == NULL) {
@@ -286,7 +278,7 @@
 			break;
 		default:	/* no escape character	*/
 			/* do not output unprintable characters */
-			if (!isprint(ch))
+			if (!isprint(msg[i_msg]))
 				break;
 			/* check if new mto needs to be created */
 			if (buffer->current_line == NULL) {
@@ -295,7 +287,7 @@
 				if (rc)
 					return i_msg;
 			}
-			*buffer->current_line++ = sclp_ascebc(ch);
+			*buffer->current_line++ = sclp_ascebc(msg[i_msg]);
 			buffer->current_length++;
 			break;
 		}
diff -urN linux-2.6/drivers/s390/char/sclp_rw.h linux-2.6-s390/drivers/s390/char/sclp_rw.h
--- linux-2.6/drivers/s390/char/sclp_rw.h	Fri Oct 17 23:43:16 2003
+++ linux-2.6-s390/drivers/s390/char/sclp_rw.h	Tue Oct 21 16:37:39 2003
@@ -89,7 +89,7 @@
 struct sclp_buffer *sclp_make_buffer(void *, unsigned short, unsigned short);
 void *sclp_unmake_buffer(struct sclp_buffer *);
 int sclp_buffer_space(struct sclp_buffer *);
-int sclp_write(struct sclp_buffer *buffer, const unsigned char *, int, int);
+int sclp_write(struct sclp_buffer *buffer, const unsigned char *, int);
 void sclp_emit_buffer(struct sclp_buffer *,void (*)(struct sclp_buffer *,int));
 void sclp_set_columns(struct sclp_buffer *, unsigned short);
 void sclp_set_htab(struct sclp_buffer *, unsigned short);
diff -urN linux-2.6/drivers/s390/char/sclp_tty.c linux-2.6-s390/drivers/s390/char/sclp_tty.c
--- linux-2.6/drivers/s390/char/sclp_tty.c	Fri Oct 17 23:42:55 2003
+++ linux-2.6-s390/drivers/s390/char/sclp_tty.c	Tue Oct 21 16:37:39 2003
@@ -322,7 +322,7 @@
  * Write a string to the sclp tty.
  */
 static void
-sclp_tty_write_string(const unsigned char *str, int count, int from_user)
+sclp_tty_write_string(const unsigned char *str, int count)
 {
 	unsigned long flags;
 	void *page;
@@ -348,8 +348,8 @@
 						       sclp_ioctls.htab);
 		}
 		/* try to write the string to the current output buffer */
-		written = sclp_write(sclp_ttybuf, str, count, from_user);
-		if (written == -EFAULT || written == count)
+		written = sclp_write(sclp_ttybuf, str, count);
+		if (written == count)
 			break;
 		/*
 		 * Not all characters could be written to the current
@@ -389,12 +389,32 @@
 sclp_tty_write(struct tty_struct *tty, int from_user,
 	       const unsigned char *buf, int count)
 {
+	int length, ret;
+
 	if (sclp_tty_chars_count > 0) {
-		sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0);
+		sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count);
 		sclp_tty_chars_count = 0;
 	}
-	sclp_tty_write_string(buf, count, from_user);
-	return count;
+	if (!from_user) {
+		sclp_tty_write_string(buf, count);
+		return count;
+	}
+	ret = 0;
+	while (count > 0) {
+		length = count < SCLP_TTY_BUF_SIZE ?
+			count : SCLP_TTY_BUF_SIZE;
+		length -= copy_from_user(sclp_tty_chars, buf, length);
+		if (length == 0) {
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
+		sclp_tty_write_string(sclp_tty_chars, length);
+		buf += length;
+		count -= length;
+		ret += length;
+	}
+	return ret;
 }
 
 /*
@@ -412,7 +432,7 @@
 {
 	sclp_tty_chars[sclp_tty_chars_count++] = ch;
 	if (ch == '\n' || sclp_tty_chars_count >= SCLP_TTY_BUF_SIZE) {
-		sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0);
+		sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count);
 		sclp_tty_chars_count = 0;
 	}
 }
@@ -425,7 +445,7 @@
 sclp_tty_flush_chars(struct tty_struct *tty)
 {
 	if (sclp_tty_chars_count > 0) {
-		sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0);
+		sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count);
 		sclp_tty_chars_count = 0;
 	}
 }
@@ -464,7 +484,7 @@
 sclp_tty_flush_buffer(struct tty_struct *tty)
 {
 	if (sclp_tty_chars_count > 0) {
-		sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0);
+		sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count);
 		sclp_tty_chars_count = 0;
 	}
 }

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2003-10-21 15:13 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-10-21 15:10 [PATCH] s390 (8/8): console driver fixes Martin Schwidefsky

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

all inboxes | Powered by JetHome®