diff options
author | Amit Shah <amit.shah@redhat.com> | 2009-12-21 10:56:45 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2010-02-23 22:52:53 -0500 |
commit | b766ceed5bbf04ae153389f5a15f53b9b6106a35 (patch) | |
tree | 92a5769e001f6eb7888f287c3917608137c53033 /drivers/char/virtio_console.c | |
parent | 17634ba25544d60af1968982929150efad755032 (diff) |
virtio: console: Prepare for writing to userspace buffers
When ports get advertised as char devices, the buffers will come from
userspace. Equip the fill_readbuf function with the ability to write
to userspace buffers.
Signed-off-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/char/virtio_console.c')
-rw-r--r-- | drivers/char/virtio_console.c | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index a70f2b3a9e64..8e447e1e12bc 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -358,7 +358,8 @@ fail: | |||
358 | * Give out the data that's requested from the buffer that we have | 358 | * Give out the data that's requested from the buffer that we have |
359 | * queued up. | 359 | * queued up. |
360 | */ | 360 | */ |
361 | static ssize_t fill_readbuf(struct port *port, char *out_buf, size_t out_count) | 361 | static ssize_t fill_readbuf(struct port *port, char *out_buf, size_t out_count, |
362 | bool to_user) | ||
362 | { | 363 | { |
363 | struct port_buffer *buf; | 364 | struct port_buffer *buf; |
364 | unsigned long flags; | 365 | unsigned long flags; |
@@ -367,12 +368,18 @@ static ssize_t fill_readbuf(struct port *port, char *out_buf, size_t out_count) | |||
367 | return 0; | 368 | return 0; |
368 | 369 | ||
369 | buf = port->inbuf; | 370 | buf = port->inbuf; |
370 | if (out_count > buf->len - buf->offset) | 371 | out_count = min(out_count, buf->len - buf->offset); |
371 | out_count = buf->len - buf->offset; | ||
372 | 372 | ||
373 | memcpy(out_buf, buf->buf + buf->offset, out_count); | 373 | if (to_user) { |
374 | ssize_t ret; | ||
375 | |||
376 | ret = copy_to_user(out_buf, buf->buf + buf->offset, out_count); | ||
377 | if (ret) | ||
378 | return -EFAULT; | ||
379 | } else { | ||
380 | memcpy(out_buf, buf->buf + buf->offset, out_count); | ||
381 | } | ||
374 | 382 | ||
375 | /* Return the number of bytes actually copied */ | ||
376 | buf->offset += out_count; | 383 | buf->offset += out_count; |
377 | 384 | ||
378 | if (buf->offset == buf->len) { | 385 | if (buf->offset == buf->len) { |
@@ -388,6 +395,7 @@ static ssize_t fill_readbuf(struct port *port, char *out_buf, size_t out_count) | |||
388 | 395 | ||
389 | spin_unlock_irqrestore(&port->inbuf_lock, flags); | 396 | spin_unlock_irqrestore(&port->inbuf_lock, flags); |
390 | } | 397 | } |
398 | /* Return the number of bytes actually copied */ | ||
391 | return out_count; | 399 | return out_count; |
392 | } | 400 | } |
393 | 401 | ||
@@ -431,7 +439,7 @@ static int get_chars(u32 vtermno, char *buf, int count) | |||
431 | /* If we don't have an input queue yet, we can't get input. */ | 439 | /* If we don't have an input queue yet, we can't get input. */ |
432 | BUG_ON(!port->in_vq); | 440 | BUG_ON(!port->in_vq); |
433 | 441 | ||
434 | return fill_readbuf(port, buf, count); | 442 | return fill_readbuf(port, buf, count, false); |
435 | } | 443 | } |
436 | 444 | ||
437 | static void resize_console(struct port *port) | 445 | static void resize_console(struct port *port) |