X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fppc%2F4xx_io%2Fserial_sicc.c;h=f0728f3c0e7b8be55f38971b8913cf1f7c096919;hb=6f71f83334a552167ccbbd42fe5dd979428c89e4;hp=4a0f3119a749a928e7d5daf3a35f9d6c3fa4806d;hpb=8d40237c730b8be87c1b80a5d96b9c603fefa829;p=linux-2.6.git diff --git a/arch/ppc/4xx_io/serial_sicc.c b/arch/ppc/4xx_io/serial_sicc.c index 4a0f3119a..f0728f3c0 100644 --- a/arch/ppc/4xx_io/serial_sicc.c +++ b/arch/ppc/4xx_io/serial_sicc.c @@ -51,12 +51,12 @@ #include #include #include -#include #include #include #include #include +#include #include @@ -933,7 +933,7 @@ static void siccuart_flush_chars(struct tty_struct *tty) restore_flags(flags); } -static int siccuart_write(struct tty_struct *tty, +static int siccuart_write(struct tty_struct *tty, int from_user, const u_char * buf, int count) { struct SICC_info *info = tty->driver_data; @@ -944,23 +944,58 @@ static int siccuart_write(struct tty_struct *tty, return 0; save_flags(flags); - cli(); - while (1) { - c = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SICC_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) - break; - memcpy(info->xmit.buf + info->xmit.head, buf, c); - info->xmit.head = (info->xmit.head + c) & - (SICC_XMIT_SIZE - 1); - buf += c; - count -= c; - ret += c; + if (from_user) { + down(&tmp_buf_sem); + while (1) { + int c1; + c = CIRC_SPACE_TO_END(info->xmit.head, + info->xmit.tail, + SICC_XMIT_SIZE); + if (count < c) + c = count; + if (c <= 0) + break; + + c -= copy_from_user(tmp_buf, buf, c); + if (!c) { + if (!ret) + ret = -EFAULT; + break; + } + cli(); + c1 = CIRC_SPACE_TO_END(info->xmit.head, + info->xmit.tail, + SICC_XMIT_SIZE); + if (c1 < c) + c = c1; + memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c); + info->xmit.head = (info->xmit.head + c) & + (SICC_XMIT_SIZE - 1); + restore_flags(flags); + buf += c; + count -= c; + ret += c; + } + up(&tmp_buf_sem); + } else { + cli(); + while (1) { + c = CIRC_SPACE_TO_END(info->xmit.head, + info->xmit.tail, + SICC_XMIT_SIZE); + if (count < c) + c = count; + if (c <= 0) + break; + memcpy(info->xmit.buf + info->xmit.head, buf, c); + info->xmit.head = (info->xmit.head + c) & + (SICC_XMIT_SIZE - 1); + buf += c; + count -= c; + ret += c; + } + restore_flags(flags); } - restore_flags(flags); if (info->xmit.head != info->xmit.tail && !tty->stopped && !tty->hw_stopped)