diff options
-rw-r--r-- | drivers/char/virtio_console.c | 67 |
1 files changed, 46 insertions, 21 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 6bbf707f9e33..82f5180d4a37 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -32,6 +32,18 @@ | |||
32 | * across multiple devices and multiple ports per device. | 32 | * across multiple devices and multiple ports per device. |
33 | */ | 33 | */ |
34 | struct ports_driver_data { | 34 | struct ports_driver_data { |
35 | /* | ||
36 | * This is used to keep track of the number of hvc consoles | ||
37 | * spawned by this driver. This number is given as the first | ||
38 | * argument to hvc_alloc(). To correctly map an initial | ||
39 | * console spawned via hvc_instantiate to the console being | ||
40 | * hooked up via hvc_alloc, we need to pass the same vtermno. | ||
41 | * | ||
42 | * We also just assume the first console being initialised was | ||
43 | * the first one that got used as the initial console. | ||
44 | */ | ||
45 | unsigned int next_vtermno; | ||
46 | |||
35 | /* All the console devices handled by this driver */ | 47 | /* All the console devices handled by this driver */ |
36 | struct list_head consoles; | 48 | struct list_head consoles; |
37 | }; | 49 | }; |
@@ -69,9 +81,6 @@ struct port { | |||
69 | u32 vtermno; | 81 | u32 vtermno; |
70 | }; | 82 | }; |
71 | 83 | ||
72 | /* We have one port ready to go immediately, for a console. */ | ||
73 | static struct port console; | ||
74 | |||
75 | /* This is the very early arch-specified put chars function. */ | 84 | /* This is the very early arch-specified put chars function. */ |
76 | static int (*early_put_chars)(u32, const char *, int); | 85 | static int (*early_put_chars)(u32, const char *, int); |
77 | 86 | ||
@@ -299,6 +308,30 @@ int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)) | |||
299 | return hvc_instantiate(0, 0, &hv_ops); | 308 | return hvc_instantiate(0, 0, &hv_ops); |
300 | } | 309 | } |
301 | 310 | ||
311 | static struct port *__devinit add_port(u32 vtermno) | ||
312 | { | ||
313 | struct port *port; | ||
314 | |||
315 | port = kmalloc(sizeof(*port), GFP_KERNEL); | ||
316 | if (!port) | ||
317 | return NULL; | ||
318 | |||
319 | port->inbuf = alloc_buf(PAGE_SIZE); | ||
320 | if (!port->inbuf) { | ||
321 | kfree(port); | ||
322 | return NULL; | ||
323 | } | ||
324 | port->hvc = NULL; | ||
325 | port->vtermno = vtermno; | ||
326 | return port; | ||
327 | } | ||
328 | |||
329 | static void free_port(struct port *port) | ||
330 | { | ||
331 | free_buf(port->inbuf); | ||
332 | kfree(port); | ||
333 | } | ||
334 | |||
302 | /* | 335 | /* |
303 | * Once we're further in boot, we get probed like any other virtio | 336 | * Once we're further in boot, we get probed like any other virtio |
304 | * device. At this stage we set up the output virtqueue. | 337 | * device. At this stage we set up the output virtqueue. |
@@ -318,24 +351,16 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) | |||
318 | struct port *port; | 351 | struct port *port; |
319 | int err; | 352 | int err; |
320 | 353 | ||
321 | port = &console; | 354 | port = add_port(pdrvdata.next_vtermno); |
322 | if (port->vdev) { | 355 | if (!port) { |
323 | dev_warn(&port->vdev->dev, | 356 | err = -ENOMEM; |
324 | "Multiple virtio-console devices not supported yet\n"); | 357 | goto fail; |
325 | return -EEXIST; | ||
326 | } | 358 | } |
327 | 359 | ||
328 | /* Attach this port to this virtio_device, and vice-versa. */ | 360 | /* Attach this port to this virtio_device, and vice-versa. */ |
329 | port->vdev = vdev; | 361 | port->vdev = vdev; |
330 | vdev->priv = port; | 362 | vdev->priv = port; |
331 | 363 | ||
332 | /* This is the scratch page we use to receive console input */ | ||
333 | port->inbuf = alloc_buf(PAGE_SIZE); | ||
334 | if (!port->inbuf) { | ||
335 | err = -ENOMEM; | ||
336 | goto fail; | ||
337 | } | ||
338 | |||
339 | /* Find the queues. */ | 364 | /* Find the queues. */ |
340 | err = vdev->config->find_vqs(vdev, 2, vqs, callbacks, names); | 365 | err = vdev->config->find_vqs(vdev, 2, vqs, callbacks, names); |
341 | if (err) | 366 | if (err) |
@@ -346,17 +371,16 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) | |||
346 | 371 | ||
347 | /* | 372 | /* |
348 | * The first argument of hvc_alloc() is the virtual console | 373 | * The first argument of hvc_alloc() is the virtual console |
349 | * number, so we use zero. The second argument is the | 374 | * number. The second argument is the parameter for the |
350 | * parameter for the notification mechanism (like irq | 375 | * notification mechanism (like irq number). We currently |
351 | * number). We currently leave this as zero, virtqueues have | 376 | * leave this as zero, virtqueues have implicit notifications. |
352 | * implicit notifications. | ||
353 | * | 377 | * |
354 | * The third argument is a "struct hv_ops" containing the | 378 | * The third argument is a "struct hv_ops" containing the |
355 | * put_chars(), get_chars(), notifier_add() and notifier_del() | 379 | * put_chars(), get_chars(), notifier_add() and notifier_del() |
356 | * pointers. The final argument is the output buffer size: we | 380 | * pointers. The final argument is the output buffer size: we |
357 | * can do any size, so we put PAGE_SIZE here. | 381 | * can do any size, so we put PAGE_SIZE here. |
358 | */ | 382 | */ |
359 | port->hvc = hvc_alloc(0, 0, &hv_ops, PAGE_SIZE); | 383 | port->hvc = hvc_alloc(port->vtermno, 0, &hv_ops, PAGE_SIZE); |
360 | if (IS_ERR(port->hvc)) { | 384 | if (IS_ERR(port->hvc)) { |
361 | err = PTR_ERR(port->hvc); | 385 | err = PTR_ERR(port->hvc); |
362 | goto free_vqs; | 386 | goto free_vqs; |
@@ -364,6 +388,7 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) | |||
364 | 388 | ||
365 | /* Add to vtermno list. */ | 389 | /* Add to vtermno list. */ |
366 | spin_lock_irq(&pdrvdata_lock); | 390 | spin_lock_irq(&pdrvdata_lock); |
391 | pdrvdata.next_vtermno++; | ||
367 | list_add(&port->list, &pdrvdata.consoles); | 392 | list_add(&port->list, &pdrvdata.consoles); |
368 | spin_unlock_irq(&pdrvdata_lock); | 393 | spin_unlock_irq(&pdrvdata_lock); |
369 | 394 | ||
@@ -377,7 +402,7 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) | |||
377 | free_vqs: | 402 | free_vqs: |
378 | vdev->config->del_vqs(vdev); | 403 | vdev->config->del_vqs(vdev); |
379 | free: | 404 | free: |
380 | free_buf(port->inbuf); | 405 | free_port(port); |
381 | fail: | 406 | fail: |
382 | return err; | 407 | return err; |
383 | } | 408 | } |