aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/virtio_console.c
diff options
context:
space:
mode:
authorAmit Shah <amit.shah@redhat.com>2010-01-18 08:45:11 -0500
committerRusty Russell <rusty@rustcorp.com.au>2010-02-23 22:52:49 -0500
commit2658a79acf014deb0eaff2063f8f7a2b59f41285 (patch)
treea8e8abe338f79789d31eeac8aadd649e947f2ad1 /drivers/char/virtio_console.c
parentcfa6d3792550c9eac51887181358954e6515da6b (diff)
virtio: console: Separate out find_vqs operation into a different function
With support for multiple ports, each port will have its own input and output vqs. Prepare the probe function for this change. 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.c98
1 files changed, 86 insertions, 12 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 11e5fafcca52..75c5a3512ecd 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -74,7 +74,9 @@ struct console {
74 * ports for that device (vdev->priv). 74 * ports for that device (vdev->priv).
75 */ 75 */
76struct ports_device { 76struct ports_device {
77 struct virtqueue *in_vq, *out_vq; 77 /* Array of per-port IO virtqueues */
78 struct virtqueue **in_vqs, **out_vqs;
79
78 struct virtio_device *vdev; 80 struct virtio_device *vdev;
79}; 81};
80 82
@@ -395,8 +397,8 @@ static int __devinit add_port(struct ports_device *portdev)
395 } 397 }
396 398
397 port->portdev = portdev; 399 port->portdev = portdev;
398 port->in_vq = portdev->in_vq; 400 port->in_vq = portdev->in_vqs[0];
399 port->out_vq = portdev->out_vq; 401 port->out_vq = portdev->out_vqs[0];
400 402
401 port->inbuf = alloc_buf(PAGE_SIZE); 403 port->inbuf = alloc_buf(PAGE_SIZE);
402 if (!port->inbuf) { 404 if (!port->inbuf) {
@@ -421,15 +423,87 @@ fail:
421 return err; 423 return err;
422} 424}
423 425
426static int init_vqs(struct ports_device *portdev)
427{
428 vq_callback_t **io_callbacks;
429 char **io_names;
430 struct virtqueue **vqs;
431 u32 nr_ports, nr_queues;
432 int err;
433
434 /* We currently only have one port and two queues for that port */
435 nr_ports = 1;
436 nr_queues = 2;
437
438 vqs = kmalloc(nr_queues * sizeof(struct virtqueue *), GFP_KERNEL);
439 if (!vqs) {
440 err = -ENOMEM;
441 goto fail;
442 }
443 io_callbacks = kmalloc(nr_queues * sizeof(vq_callback_t *), GFP_KERNEL);
444 if (!io_callbacks) {
445 err = -ENOMEM;
446 goto free_vqs;
447 }
448 io_names = kmalloc(nr_queues * sizeof(char *), GFP_KERNEL);
449 if (!io_names) {
450 err = -ENOMEM;
451 goto free_callbacks;
452 }
453 portdev->in_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *),
454 GFP_KERNEL);
455 if (!portdev->in_vqs) {
456 err = -ENOMEM;
457 goto free_names;
458 }
459 portdev->out_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *),
460 GFP_KERNEL);
461 if (!portdev->out_vqs) {
462 err = -ENOMEM;
463 goto free_invqs;
464 }
465
466 io_callbacks[0] = hvc_handle_input;
467 io_callbacks[1] = NULL;
468 io_names[0] = "input";
469 io_names[1] = "output";
470
471 /* Find the queues. */
472 err = portdev->vdev->config->find_vqs(portdev->vdev, nr_queues, vqs,
473 io_callbacks,
474 (const char **)io_names);
475 if (err)
476 goto free_outvqs;
477
478 portdev->in_vqs[0] = vqs[0];
479 portdev->out_vqs[0] = vqs[1];
480
481 kfree(io_callbacks);
482 kfree(io_names);
483 kfree(vqs);
484
485 return 0;
486
487free_names:
488 kfree(io_names);
489free_callbacks:
490 kfree(io_callbacks);
491free_outvqs:
492 kfree(portdev->out_vqs);
493free_invqs:
494 kfree(portdev->in_vqs);
495free_vqs:
496 kfree(vqs);
497fail:
498 return err;
499}
500
424/* 501/*
425 * Once we're further in boot, we get probed like any other virtio 502 * Once we're further in boot, we get probed like any other virtio
426 * device. 503 * device.
427 */ 504 */
428static int __devinit virtcons_probe(struct virtio_device *vdev) 505static int __devinit virtcons_probe(struct virtio_device *vdev)
429{ 506{
430 vq_callback_t *callbacks[] = { hvc_handle_input, NULL};
431 const char *names[] = { "input", "output" };
432 struct virtqueue *vqs[2];
433 struct ports_device *portdev; 507 struct ports_device *portdev;
434 int err; 508 int err;
435 509
@@ -443,13 +517,11 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
443 portdev->vdev = vdev; 517 portdev->vdev = vdev;
444 vdev->priv = portdev; 518 vdev->priv = portdev;
445 519
446 /* Find the queues. */ 520 err = init_vqs(portdev);
447 err = vdev->config->find_vqs(vdev, 2, vqs, callbacks, names); 521 if (err < 0) {
448 if (err) 522 dev_err(&vdev->dev, "Error %d initializing vqs\n", err);
449 goto free; 523 goto free;
450 524 }
451 portdev->in_vq = vqs[0];
452 portdev->out_vq = vqs[1];
453 525
454 /* We only have one port. */ 526 /* We only have one port. */
455 err = add_port(portdev); 527 err = add_port(portdev);
@@ -462,6 +534,8 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
462 534
463free_vqs: 535free_vqs:
464 vdev->config->del_vqs(vdev); 536 vdev->config->del_vqs(vdev);
537 kfree(portdev->in_vqs);
538 kfree(portdev->out_vqs);
465free: 539free:
466 kfree(portdev); 540 kfree(portdev);
467fail: 541fail: