diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/virtio_console.c | 60 |
1 files changed, 34 insertions, 26 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 26e238cd7d2..1d844a43a6b 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -28,12 +28,12 @@ static struct virtio_device *vdev; static unsigned int in_len; static char *in, *inbuf; -/* The operations for our console. */ -static struct hv_ops virtio_cons; - /* The hvc device */ static struct hvc_struct *hvc; +/* This is the very early arch-specified put chars function. */ +static int (*early_put_chars)(u32, const char *, int); + /* * The put_chars() callback is pretty straightforward. * @@ -47,6 +47,9 @@ static int put_chars(u32 vtermno, const char *buf, int count) struct scatterlist sg[1]; unsigned int len; + if (unlikely(early_put_chars)) + return early_put_chars(vtermno, buf, count); + /* This is a convenient routine to initialize a single-elem sg list */ sg_init_one(sg, buf, count); @@ -118,21 +121,6 @@ static int get_chars(u32 vtermno, char *buf, int count) } /* - * Console drivers are initialized very early so boot messages can go - * out, so we do things slightly differently from the generic virtio - * initialization of the net and block drivers. - * - * At this stage, the console is output-only. It's too early to set - * up a virtqueue, so we let the drivers do some boutique early-output - * thing. - */ -int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)) -{ - virtio_cons.put_chars = put_chars; - return hvc_instantiate(0, 0, &virtio_cons); -} - -/* * virtio console configuration. This supports: * - console resize */ @@ -174,6 +162,30 @@ static void hvc_handle_input(struct virtqueue *vq) hvc_kick(); } +/* The operations for the console. */ +static struct hv_ops hv_ops = { + .get_chars = get_chars, + .put_chars = put_chars, + .notifier_add = notifier_add_vio, + .notifier_del = notifier_del_vio, + .notifier_hangup = notifier_del_vio, +}; + +/* + * Console drivers are initialized very early so boot messages can go + * out, so we do things slightly differently from the generic virtio + * initialization of the net and block drivers. + * + * At this stage, the console is output-only. It's too early to set + * up a virtqueue, so we let the drivers do some boutique early-output + * thing. + */ +int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)) +{ + early_put_chars = put_chars; + return hvc_instantiate(0, 0, &hv_ops); +} + /* * Once we're further in boot, we get probed like any other virtio * device. At this stage we set up the output virtqueue. @@ -209,13 +221,6 @@ static int __devinit virtcons_probe(struct virtio_device *dev) in_vq = vqs[0]; out_vq = vqs[1]; - /* Start using the new console output. */ - virtio_cons.get_chars = get_chars; - virtio_cons.put_chars = put_chars; - virtio_cons.notifier_add = notifier_add_vio; - virtio_cons.notifier_del = notifier_del_vio; - virtio_cons.notifier_hangup = notifier_del_vio; - /* * The first argument of hvc_alloc() is the virtual console * number, so we use zero. The second argument is the @@ -228,7 +233,7 @@ static int __devinit virtcons_probe(struct virtio_device *dev) * pointers. The final argument is the output buffer size: we * can do any size, so we put PAGE_SIZE here. */ - hvc = hvc_alloc(0, 0, &virtio_cons, PAGE_SIZE); + hvc = hvc_alloc(0, 0, &hv_ops, PAGE_SIZE); if (IS_ERR(hvc)) { err = PTR_ERR(hvc); goto free_vqs; @@ -236,6 +241,9 @@ static int __devinit virtcons_probe(struct virtio_device *dev) /* Register the input buffer the first time. */ add_inbuf(); + + /* Start using the new console output. */ + early_put_chars = NULL; return 0; free_vqs: |