diff options
Diffstat (limited to 'drivers/char/virtio_console.c')
-rw-r--r-- | drivers/char/virtio_console.c | 23 |
1 files changed, 12 insertions, 11 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index b2fc2abedc79..e88f84390428 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -229,7 +229,6 @@ struct port { | |||
229 | bool guest_connected; | 229 | bool guest_connected; |
230 | }; | 230 | }; |
231 | 231 | ||
232 | #define MAX_SPLICE_PAGES 32 | ||
233 | /* This is the very early arch-specified put chars function. */ | 232 | /* This is the very early arch-specified put chars function. */ |
234 | static int (*early_put_chars)(u32, const char *, int); | 233 | static int (*early_put_chars)(u32, const char *, int); |
235 | 234 | ||
@@ -482,15 +481,16 @@ struct buffer_token { | |||
482 | void *buf; | 481 | void *buf; |
483 | struct scatterlist *sg; | 482 | struct scatterlist *sg; |
484 | } u; | 483 | } u; |
485 | bool sgpages; | 484 | /* If sgpages == 0 then buf is used, else sg is used */ |
485 | unsigned int sgpages; | ||
486 | }; | 486 | }; |
487 | 487 | ||
488 | static void reclaim_sg_pages(struct scatterlist *sg) | 488 | static void reclaim_sg_pages(struct scatterlist *sg, unsigned int nrpages) |
489 | { | 489 | { |
490 | int i; | 490 | int i; |
491 | struct page *page; | 491 | struct page *page; |
492 | 492 | ||
493 | for (i = 0; i < MAX_SPLICE_PAGES; i++) { | 493 | for (i = 0; i < nrpages; i++) { |
494 | page = sg_page(&sg[i]); | 494 | page = sg_page(&sg[i]); |
495 | if (!page) | 495 | if (!page) |
496 | break; | 496 | break; |
@@ -511,7 +511,7 @@ static void reclaim_consumed_buffers(struct port *port) | |||
511 | } | 511 | } |
512 | while ((tok = virtqueue_get_buf(port->out_vq, &len))) { | 512 | while ((tok = virtqueue_get_buf(port->out_vq, &len))) { |
513 | if (tok->sgpages) | 513 | if (tok->sgpages) |
514 | reclaim_sg_pages(tok->u.sg); | 514 | reclaim_sg_pages(tok->u.sg, tok->sgpages); |
515 | else | 515 | else |
516 | kfree(tok->u.buf); | 516 | kfree(tok->u.buf); |
517 | kfree(tok); | 517 | kfree(tok); |
@@ -581,7 +581,7 @@ static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count, | |||
581 | tok = kmalloc(sizeof(*tok), GFP_ATOMIC); | 581 | tok = kmalloc(sizeof(*tok), GFP_ATOMIC); |
582 | if (!tok) | 582 | if (!tok) |
583 | return -ENOMEM; | 583 | return -ENOMEM; |
584 | tok->sgpages = false; | 584 | tok->sgpages = 0; |
585 | tok->u.buf = in_buf; | 585 | tok->u.buf = in_buf; |
586 | 586 | ||
587 | sg_init_one(sg, in_buf, in_count); | 587 | sg_init_one(sg, in_buf, in_count); |
@@ -597,7 +597,7 @@ static ssize_t send_pages(struct port *port, struct scatterlist *sg, int nents, | |||
597 | tok = kmalloc(sizeof(*tok), GFP_ATOMIC); | 597 | tok = kmalloc(sizeof(*tok), GFP_ATOMIC); |
598 | if (!tok) | 598 | if (!tok) |
599 | return -ENOMEM; | 599 | return -ENOMEM; |
600 | tok->sgpages = true; | 600 | tok->sgpages = nents; |
601 | tok->u.sg = sg; | 601 | tok->u.sg = sg; |
602 | 602 | ||
603 | return __send_to_port(port, sg, nents, in_count, tok, nonblock); | 603 | return __send_to_port(port, sg, nents, in_count, tok, nonblock); |
@@ -797,6 +797,7 @@ out: | |||
797 | 797 | ||
798 | struct sg_list { | 798 | struct sg_list { |
799 | unsigned int n; | 799 | unsigned int n; |
800 | unsigned int size; | ||
800 | size_t len; | 801 | size_t len; |
801 | struct scatterlist *sg; | 802 | struct scatterlist *sg; |
802 | }; | 803 | }; |
@@ -807,7 +808,7 @@ static int pipe_to_sg(struct pipe_inode_info *pipe, struct pipe_buffer *buf, | |||
807 | struct sg_list *sgl = sd->u.data; | 808 | struct sg_list *sgl = sd->u.data; |
808 | unsigned int offset, len; | 809 | unsigned int offset, len; |
809 | 810 | ||
810 | if (sgl->n == MAX_SPLICE_PAGES) | 811 | if (sgl->n == sgl->size) |
811 | return 0; | 812 | return 0; |
812 | 813 | ||
813 | /* Try lock this page */ | 814 | /* Try lock this page */ |
@@ -868,12 +869,12 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe, | |||
868 | 869 | ||
869 | sgl.n = 0; | 870 | sgl.n = 0; |
870 | sgl.len = 0; | 871 | sgl.len = 0; |
871 | sgl.sg = kmalloc(sizeof(struct scatterlist) * MAX_SPLICE_PAGES, | 872 | sgl.size = pipe->nrbufs; |
872 | GFP_KERNEL); | 873 | sgl.sg = kmalloc(sizeof(struct scatterlist) * sgl.size, GFP_KERNEL); |
873 | if (unlikely(!sgl.sg)) | 874 | if (unlikely(!sgl.sg)) |
874 | return -ENOMEM; | 875 | return -ENOMEM; |
875 | 876 | ||
876 | sg_init_table(sgl.sg, MAX_SPLICE_PAGES); | 877 | sg_init_table(sgl.sg, sgl.size); |
877 | ret = __splice_from_pipe(pipe, &sd, pipe_to_sg); | 878 | ret = __splice_from_pipe(pipe, &sd, pipe_to_sg); |
878 | if (likely(ret > 0)) | 879 | if (likely(ret > 0)) |
879 | ret = send_pages(port, sgl.sg, sgl.n, sgl.len, true); | 880 | ret = send_pages(port, sgl.sg, sgl.n, sgl.len, true); |