From: Martin Schwidefsky - 3215: Adapt to notify api change in cio. - 3215/sclp: move copy_from_user out of locked code. --- 25-akpm/drivers/s390/char/con3215.c | 92 ++++++++++++++--------------------- 25-akpm/drivers/s390/char/sclp_con.c | 4 - 25-akpm/drivers/s390/char/sclp_rw.c | 16 +----- 25-akpm/drivers/s390/char/sclp_rw.h | 2 25-akpm/drivers/s390/char/sclp_tty.c | 38 +++++++++++--- 5 files changed, 75 insertions(+), 77 deletions(-) diff -puN drivers/s390/char/con3215.c~s390-03-console-driver drivers/s390/char/con3215.c --- 25/drivers/s390/char/con3215.c~s390-03-console-driver Thu Jan 8 14:11:29 2004 +++ 25-akpm/drivers/s390/char/con3215.c Thu Jan 8 14:11:29 2004 @@ -96,6 +96,7 @@ struct raw3215_info { 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 @@ raw3215_make_room(struct raw3215_info *r /* * 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_write(struct raw3215_info *raw, 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 @@ raw3215_write(struct raw3215_info *raw, } spin_unlock_irqrestore(raw->lock, flags); } - - return ret; } /* @@ -752,11 +721,12 @@ raw3215_probe (struct ccw_device *cdev) return 0; } -static int +static void raw3215_remove (struct ccw_device *cdev) { struct raw3215_info *raw; + ccw_device_set_offline(cdev); raw = cdev->dev.driver_data; if (raw) { cdev->dev.driver_data = NULL; @@ -764,7 +734,6 @@ raw3215_remove (struct ccw_device *cdev) kfree(raw->buffer); kfree(raw); } - return 0; } static int @@ -825,7 +794,7 @@ con3215_write(struct console *co, const 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 @@ tty3215_write(struct tty_struct * tty, i 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 -puN drivers/s390/char/sclp_con.c~s390-03-console-driver drivers/s390/char/sclp_con.c --- 25/drivers/s390/char/sclp_con.c~s390-03-console-driver Thu Jan 8 14:11:29 2004 +++ 25-akpm/drivers/s390/char/sclp_con.c Thu Jan 8 14:11:29 2004 @@ -134,8 +134,8 @@ sclp_console_write(struct console *conso } /* 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 -puN drivers/s390/char/sclp_rw.c~s390-03-console-driver drivers/s390/char/sclp_rw.c --- 25/drivers/s390/char/sclp_rw.c~s390-03-console-driver Thu Jan 8 14:11:29 2004 +++ 25-akpm/drivers/s390/char/sclp_rw.c Thu Jan 8 14:11:29 2004 @@ -175,11 +175,9 @@ sclp_finalize_mto(struct sclp_buffer *bu * 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 @@ sclp_write(struct sclp_buffer *buffer, * 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 @@ sclp_write(struct sclp_buffer *buffer, 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 @@ sclp_write(struct sclp_buffer *buffer, if (rc) return i_msg; } - *buffer->current_line++ = sclp_ascebc(ch); + *buffer->current_line++ = sclp_ascebc(msg[i_msg]); buffer->current_length++; break; } diff -puN drivers/s390/char/sclp_rw.h~s390-03-console-driver drivers/s390/char/sclp_rw.h --- 25/drivers/s390/char/sclp_rw.h~s390-03-console-driver Thu Jan 8 14:11:29 2004 +++ 25-akpm/drivers/s390/char/sclp_rw.h Thu Jan 8 14:11:29 2004 @@ -89,7 +89,7 @@ int sclp_rw_init(void); 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 -puN drivers/s390/char/sclp_tty.c~s390-03-console-driver drivers/s390/char/sclp_tty.c --- 25/drivers/s390/char/sclp_tty.c~s390-03-console-driver Thu Jan 8 14:11:29 2004 +++ 25-akpm/drivers/s390/char/sclp_tty.c Thu Jan 8 14:11:29 2004 @@ -322,7 +322,7 @@ sclp_tty_timeout(unsigned long data) * 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_tty_write_string(const unsigned cha 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 @@ static int 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_put_char(struct tty_struct *tty { 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 @@ static void 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 @@ static void 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; } } _