diff options
author | Christian Borntraeger <borntraeger@de.ibm.com> | 2008-06-20 09:24:15 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2008-07-24 22:06:06 -0400 |
commit | 91fcad19d03ed67cb50fd0e1913a8b89cc3ed3ec (patch) | |
tree | 90d4f8ded6547615f21bcef8995eee133d8c2510 /drivers/char/virtio_console.c | |
parent | 611e097d7707741a336a0677d9d69bec40f29f3d (diff) |
virtio_console: use virtqueue notification for hvc_console
This patch exploits the new notifier callbacks of the hvc_console. We can
use the virtio callbacks instead of the polling code.
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.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 | 40 |
1 files changed, 33 insertions, 7 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index dc17fe3a88bc..d0f4eb6fdb7f 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -46,6 +46,9 @@ static char *in, *inbuf; | |||
46 | /* The operations for our console. */ | 46 | /* The operations for our console. */ |
47 | static struct hv_ops virtio_cons; | 47 | static struct hv_ops virtio_cons; |
48 | 48 | ||
49 | /* The hvc device */ | ||
50 | static struct hvc_struct *hvc; | ||
51 | |||
49 | /*D:310 The put_chars() callback is pretty straightforward. | 52 | /*D:310 The put_chars() callback is pretty straightforward. |
50 | * | 53 | * |
51 | * We turn the characters into a scatter-gather list, add it to the output | 54 | * We turn the characters into a scatter-gather list, add it to the output |
@@ -134,6 +137,27 @@ int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)) | |||
134 | return hvc_instantiate(0, 0, &virtio_cons); | 137 | return hvc_instantiate(0, 0, &virtio_cons); |
135 | } | 138 | } |
136 | 139 | ||
140 | /* | ||
141 | * we support only one console, the hvc struct is a global var | ||
142 | * There is no need to do anything | ||
143 | */ | ||
144 | static int notifier_add_vio(struct hvc_struct *hp, int data) | ||
145 | { | ||
146 | hp->irq_requested = 1; | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | static void notifier_del_vio(struct hvc_struct *hp, int data) | ||
151 | { | ||
152 | hp->irq_requested = 0; | ||
153 | } | ||
154 | |||
155 | static void hvc_handle_input(struct virtqueue *vq) | ||
156 | { | ||
157 | if (hvc_poll(hvc)) | ||
158 | hvc_kick(); | ||
159 | } | ||
160 | |||
137 | /*D:370 Once we're further in boot, we get probed like any other virtio device. | 161 | /*D:370 Once we're further in boot, we get probed like any other virtio device. |
138 | * At this stage we set up the output virtqueue. | 162 | * At this stage we set up the output virtqueue. |
139 | * | 163 | * |
@@ -144,7 +168,6 @@ int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)) | |||
144 | static int __devinit virtcons_probe(struct virtio_device *dev) | 168 | static int __devinit virtcons_probe(struct virtio_device *dev) |
145 | { | 169 | { |
146 | int err; | 170 | int err; |
147 | struct hvc_struct *hvc; | ||
148 | 171 | ||
149 | vdev = dev; | 172 | vdev = dev; |
150 | 173 | ||
@@ -158,7 +181,7 @@ static int __devinit virtcons_probe(struct virtio_device *dev) | |||
158 | /* Find the input queue. */ | 181 | /* Find the input queue. */ |
159 | /* FIXME: This is why we want to wean off hvc: we do nothing | 182 | /* FIXME: This is why we want to wean off hvc: we do nothing |
160 | * when input comes in. */ | 183 | * when input comes in. */ |
161 | in_vq = vdev->config->find_vq(vdev, 0, NULL); | 184 | in_vq = vdev->config->find_vq(vdev, 0, hvc_handle_input); |
162 | if (IS_ERR(in_vq)) { | 185 | if (IS_ERR(in_vq)) { |
163 | err = PTR_ERR(in_vq); | 186 | err = PTR_ERR(in_vq); |
164 | goto free; | 187 | goto free; |
@@ -173,15 +196,18 @@ static int __devinit virtcons_probe(struct virtio_device *dev) | |||
173 | /* Start using the new console output. */ | 196 | /* Start using the new console output. */ |
174 | virtio_cons.get_chars = get_chars; | 197 | virtio_cons.get_chars = get_chars; |
175 | virtio_cons.put_chars = put_chars; | 198 | virtio_cons.put_chars = put_chars; |
199 | virtio_cons.notifier_add = notifier_add_vio; | ||
200 | virtio_cons.notifier_del = notifier_del_vio; | ||
176 | 201 | ||
177 | /* The first argument of hvc_alloc() is the virtual console number, so | 202 | /* The first argument of hvc_alloc() is the virtual console number, so |
178 | * we use zero. The second argument is the interrupt number; we | 203 | * we use zero. The second argument is the parameter for the |
179 | * currently leave this as zero: it would be better not to use the | 204 | * notification mechanism (like irq number). We currently leave this |
180 | * hvc mechanism and fix this (FIXME!). | 205 | * as zero, virtqueues have implicit notifications. |
181 | * | 206 | * |
182 | * The third argument is a "struct hv_ops" containing the put_chars() | 207 | * The third argument is a "struct hv_ops" containing the put_chars() |
183 | * and get_chars() pointers. The final argument is the output buffer | 208 | * get_chars(), notifier_add() and notifier_del() pointers. |
184 | * size: we can do any size, so we put PAGE_SIZE here. */ | 209 | * The final argument is the output buffer size: we can do any size, |
210 | * so we put PAGE_SIZE here. */ | ||
185 | hvc = hvc_alloc(0, 0, &virtio_cons, PAGE_SIZE); | 211 | hvc = hvc_alloc(0, 0, &virtio_cons, PAGE_SIZE); |
186 | if (IS_ERR(hvc)) { | 212 | if (IS_ERR(hvc)) { |
187 | err = PTR_ERR(hvc); | 213 | err = PTR_ERR(hvc); |