diff options
author | Amit Shah <amit.shah@redhat.com> | 2010-01-18 08:45:01 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2010-02-23 22:52:36 -0500 |
commit | fdb9a054554e1e435e927c9a47a999f026abd408 (patch) | |
tree | 4ef632d26bf6068de7ab14f99547fd94e0c939b6 /drivers/char/virtio_console.c | |
parent | 21206ede8826fd9d2eb72e05b429f3ccb1bdaff5 (diff) |
virtio: console: encapsulate buffer information in a struct
Collect port buffer, used_len, offset fields into a single structure.
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 | 70 |
1 files changed, 55 insertions, 15 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 9ea9223c5c5c..699fc98ec8d9 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -21,12 +21,24 @@ | |||
21 | #include <linux/virtio_console.h> | 21 | #include <linux/virtio_console.h> |
22 | #include "hvc_console.h" | 22 | #include "hvc_console.h" |
23 | 23 | ||
24 | struct port_buffer { | ||
25 | char *buf; | ||
26 | |||
27 | /* size of the buffer in *buf above */ | ||
28 | size_t size; | ||
29 | |||
30 | /* used length of the buffer */ | ||
31 | size_t len; | ||
32 | /* offset in the buf from which to consume data */ | ||
33 | size_t offset; | ||
34 | }; | ||
35 | |||
24 | struct port { | 36 | struct port { |
25 | struct virtqueue *in_vq, *out_vq; | 37 | struct virtqueue *in_vq, *out_vq; |
26 | struct virtio_device *vdev; | 38 | struct virtio_device *vdev; |
27 | /* This is our input buffer, and how much data is left in it. */ | 39 | |
28 | char *inbuf; | 40 | /* The current buffer from which data has to be fed to readers */ |
29 | unsigned int used_len, offset; | 41 | struct port_buffer *inbuf; |
30 | 42 | ||
31 | /* The hvc device */ | 43 | /* The hvc device */ |
32 | struct hvc_struct *hvc; | 44 | struct hvc_struct *hvc; |
@@ -38,6 +50,33 @@ static struct port console; | |||
38 | /* This is the very early arch-specified put chars function. */ | 50 | /* This is the very early arch-specified put chars function. */ |
39 | static int (*early_put_chars)(u32, const char *, int); | 51 | static int (*early_put_chars)(u32, const char *, int); |
40 | 52 | ||
53 | static void free_buf(struct port_buffer *buf) | ||
54 | { | ||
55 | kfree(buf->buf); | ||
56 | kfree(buf); | ||
57 | } | ||
58 | |||
59 | static struct port_buffer *alloc_buf(size_t buf_size) | ||
60 | { | ||
61 | struct port_buffer *buf; | ||
62 | |||
63 | buf = kmalloc(sizeof(*buf), GFP_KERNEL); | ||
64 | if (!buf) | ||
65 | goto fail; | ||
66 | buf->buf = kzalloc(buf_size, GFP_KERNEL); | ||
67 | if (!buf->buf) | ||
68 | goto free_buf; | ||
69 | buf->len = 0; | ||
70 | buf->offset = 0; | ||
71 | buf->size = buf_size; | ||
72 | return buf; | ||
73 | |||
74 | free_buf: | ||
75 | kfree(buf); | ||
76 | fail: | ||
77 | return NULL; | ||
78 | } | ||
79 | |||
41 | /* | 80 | /* |
42 | * The put_chars() callback is pretty straightforward. | 81 | * The put_chars() callback is pretty straightforward. |
43 | * | 82 | * |
@@ -79,7 +118,7 @@ static int put_chars(u32 vtermno, const char *buf, int count) | |||
79 | static void add_inbuf(struct port *port) | 118 | static void add_inbuf(struct port *port) |
80 | { | 119 | { |
81 | struct scatterlist sg[1]; | 120 | struct scatterlist sg[1]; |
82 | sg_init_one(sg, port->inbuf, PAGE_SIZE); | 121 | sg_init_one(sg, port->inbuf->buf, PAGE_SIZE); |
83 | 122 | ||
84 | /* Should always be able to add one buffer to an empty queue. */ | 123 | /* Should always be able to add one buffer to an empty queue. */ |
85 | if (port->in_vq->vq_ops->add_buf(port->in_vq, sg, 0, 1, port) < 0) | 124 | if (port->in_vq->vq_ops->add_buf(port->in_vq, sg, 0, 1, port) < 0) |
@@ -98,6 +137,7 @@ static void add_inbuf(struct port *port) | |||
98 | static int get_chars(u32 vtermno, char *buf, int count) | 137 | static int get_chars(u32 vtermno, char *buf, int count) |
99 | { | 138 | { |
100 | struct port *port; | 139 | struct port *port; |
140 | unsigned int len; | ||
101 | 141 | ||
102 | port = &console; | 142 | port = &console; |
103 | 143 | ||
@@ -105,22 +145,23 @@ static int get_chars(u32 vtermno, char *buf, int count) | |||
105 | BUG_ON(!port->in_vq); | 145 | BUG_ON(!port->in_vq); |
106 | 146 | ||
107 | /* No more in buffer? See if they've (re)used it. */ | 147 | /* No more in buffer? See if they've (re)used it. */ |
108 | if (port->offset == port->used_len) { | 148 | if (port->inbuf->offset == port->inbuf->len) { |
109 | if (!port->in_vq->vq_ops->get_buf(port->in_vq, &port->used_len)) | 149 | if (!port->in_vq->vq_ops->get_buf(port->in_vq, &len)) |
110 | return 0; | 150 | return 0; |
111 | port->offset = 0; | 151 | port->inbuf->offset = 0; |
152 | port->inbuf->len = len; | ||
112 | } | 153 | } |
113 | 154 | ||
114 | /* You want more than we have to give? Well, try wanting less! */ | 155 | /* You want more than we have to give? Well, try wanting less! */ |
115 | if (port->offset + count > port->used_len) | 156 | if (port->inbuf->offset + count > port->inbuf->len) |
116 | count = port->used_len - port->offset; | 157 | count = port->inbuf->len - port->inbuf->offset; |
117 | 158 | ||
118 | /* Copy across to their buffer and increment offset. */ | 159 | /* Copy across to their buffer and increment offset. */ |
119 | memcpy(buf, port->inbuf + port->offset, count); | 160 | memcpy(buf, port->inbuf->buf + port->inbuf->offset, count); |
120 | port->offset += count; | 161 | port->inbuf->offset += count; |
121 | 162 | ||
122 | /* Finished? Re-register buffer so Host will use it again. */ | 163 | /* Finished? Re-register buffer so Host will use it again. */ |
123 | if (port->offset == port->used_len) | 164 | if (port->inbuf->offset == port->inbuf->len) |
124 | add_inbuf(port); | 165 | add_inbuf(port); |
125 | 166 | ||
126 | return count; | 167 | return count; |
@@ -220,8 +261,7 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) | |||
220 | port->vdev = vdev; | 261 | port->vdev = vdev; |
221 | 262 | ||
222 | /* This is the scratch page we use to receive console input */ | 263 | /* This is the scratch page we use to receive console input */ |
223 | port->used_len = 0; | 264 | port->inbuf = alloc_buf(PAGE_SIZE); |
224 | port->inbuf = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
225 | if (!port->inbuf) { | 265 | if (!port->inbuf) { |
226 | err = -ENOMEM; | 266 | err = -ENOMEM; |
227 | goto fail; | 267 | goto fail; |
@@ -263,7 +303,7 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) | |||
263 | free_vqs: | 303 | free_vqs: |
264 | vdev->config->del_vqs(vdev); | 304 | vdev->config->del_vqs(vdev); |
265 | free: | 305 | free: |
266 | kfree(port->inbuf); | 306 | free_buf(port->inbuf); |
267 | fail: | 307 | fail: |
268 | return err; | 308 | return err; |
269 | } | 309 | } |