diff options
author | Amit Shah <amit.shah@redhat.com> | 2009-12-21 06:58:51 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2010-02-23 22:52:51 -0500 |
commit | f997f00bf8c3ddf748d757105afa1a7dd5297208 (patch) | |
tree | aedb212484ca3ff86ec5eb9c141a70e64df96f59 /drivers/char/virtio_console.c | |
parent | 203baab8ba3195dd929473ba95b91c2b838833e6 (diff) |
virtio: console: Introduce a send_buf function for a common path for sending data to host
Adding support for generic ports that will write to userspace will need
some code changes.
Consolidate the write routine into send_buf() and put_chars() now just
calls into the new function.
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 | 50 |
1 files changed, 33 insertions, 17 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 5096d92f5b89..d01051060be3 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -233,6 +233,38 @@ static bool port_has_data(struct port *port) | |||
233 | return ret; | 233 | return ret; |
234 | } | 234 | } |
235 | 235 | ||
236 | static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count) | ||
237 | { | ||
238 | struct scatterlist sg[1]; | ||
239 | struct virtqueue *out_vq; | ||
240 | ssize_t ret; | ||
241 | unsigned int len; | ||
242 | |||
243 | out_vq = port->out_vq; | ||
244 | |||
245 | sg_init_one(sg, in_buf, in_count); | ||
246 | ret = out_vq->vq_ops->add_buf(out_vq, sg, 1, 0, in_buf); | ||
247 | |||
248 | /* Tell Host to go! */ | ||
249 | out_vq->vq_ops->kick(out_vq); | ||
250 | |||
251 | if (ret < 0) { | ||
252 | len = 0; | ||
253 | goto fail; | ||
254 | } | ||
255 | |||
256 | /* | ||
257 | * Wait till the host acknowledges it pushed out the data we | ||
258 | * sent. Also ensure we return to userspace the number of | ||
259 | * bytes that were successfully consumed by the host. | ||
260 | */ | ||
261 | while (!out_vq->vq_ops->get_buf(out_vq, &len)) | ||
262 | cpu_relax(); | ||
263 | fail: | ||
264 | /* We're expected to return the amount of data we wrote */ | ||
265 | return len; | ||
266 | } | ||
267 | |||
236 | /* | 268 | /* |
237 | * Give out the data that's requested from the buffer that we have | 269 | * Give out the data that's requested from the buffer that we have |
238 | * queued up. | 270 | * queued up. |
@@ -280,10 +312,7 @@ static ssize_t fill_readbuf(struct port *port, char *out_buf, size_t out_count) | |||
280 | */ | 312 | */ |
281 | static int put_chars(u32 vtermno, const char *buf, int count) | 313 | static int put_chars(u32 vtermno, const char *buf, int count) |
282 | { | 314 | { |
283 | struct scatterlist sg[1]; | ||
284 | struct port *port; | 315 | struct port *port; |
285 | struct virtqueue *out_vq; | ||
286 | unsigned int len; | ||
287 | 316 | ||
288 | port = find_port_by_vtermno(vtermno); | 317 | port = find_port_by_vtermno(vtermno); |
289 | if (!port) | 318 | if (!port) |
@@ -292,20 +321,7 @@ static int put_chars(u32 vtermno, const char *buf, int count) | |||
292 | if (unlikely(early_put_chars)) | 321 | if (unlikely(early_put_chars)) |
293 | return early_put_chars(vtermno, buf, count); | 322 | return early_put_chars(vtermno, buf, count); |
294 | 323 | ||
295 | out_vq = port->out_vq; | 324 | return send_buf(port, (void *)buf, count); |
296 | /* This is a convenient routine to initialize a single-elem sg list */ | ||
297 | sg_init_one(sg, buf, count); | ||
298 | |||
299 | /* This shouldn't fail: if it does, we lose chars. */ | ||
300 | if (out_vq->vq_ops->add_buf(out_vq, sg, 1, 0, port) >= 0) { | ||
301 | /* Tell Host to go! */ | ||
302 | out_vq->vq_ops->kick(out_vq); | ||
303 | while (!out_vq->vq_ops->get_buf(out_vq, &len)) | ||
304 | cpu_relax(); | ||
305 | } | ||
306 | |||
307 | /* We're expected to return the amount of data we wrote: all of it. */ | ||
308 | return count; | ||
309 | } | 325 | } |
310 | 326 | ||
311 | /* | 327 | /* |