diff options
author | Amit Shah <amit.shah@redhat.com> | 2010-01-18 08:45:11 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2010-02-23 22:52:49 -0500 |
commit | 2658a79acf014deb0eaff2063f8f7a2b59f41285 (patch) | |
tree | a8e8abe338f79789d31eeac8aadd649e947f2ad1 /drivers/char | |
parent | cfa6d3792550c9eac51887181358954e6515da6b (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')
-rw-r--r-- | drivers/char/virtio_console.c | 98 |
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 | */ |
76 | struct ports_device { | 76 | struct 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 | ||
426 | static 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 | |||
487 | free_names: | ||
488 | kfree(io_names); | ||
489 | free_callbacks: | ||
490 | kfree(io_callbacks); | ||
491 | free_outvqs: | ||
492 | kfree(portdev->out_vqs); | ||
493 | free_invqs: | ||
494 | kfree(portdev->in_vqs); | ||
495 | free_vqs: | ||
496 | kfree(vqs); | ||
497 | fail: | ||
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 | */ |
428 | static int __devinit virtcons_probe(struct virtio_device *vdev) | 505 | static 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 | ||
463 | free_vqs: | 535 | free_vqs: |
464 | vdev->config->del_vqs(vdev); | 536 | vdev->config->del_vqs(vdev); |
537 | kfree(portdev->in_vqs); | ||
538 | kfree(portdev->out_vqs); | ||
465 | free: | 539 | free: |
466 | kfree(portdev); | 540 | kfree(portdev); |
467 | fail: | 541 | fail: |