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 | |
| 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')
| -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) |
