blob: 8e447e1e12bc27ef922fe4dbfdc14826589a0bc2 [file] [log] [blame]
Rusty Russella23ea922010-01-18 19:14:55 +05301/*
2 * Copyright (C) 2006, 2007, 2009 Rusty Russell, IBM Corporation
Amit Shah17634ba2009-12-21 21:03:25 +05303 * Copyright (C) 2009, 2010 Red Hat, Inc.
Rusty Russell31610432007-10-22 11:03:39 +10004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <linux/err.h>
20#include <linux/init.h>
Amit Shah38edf582010-01-18 19:15:05 +053021#include <linux/list.h>
22#include <linux/spinlock.h>
Rusty Russell31610432007-10-22 11:03:39 +100023#include <linux/virtio.h>
24#include <linux/virtio_console.h>
Amit Shah17634ba2009-12-21 21:03:25 +053025#include <linux/workqueue.h>
Rusty Russell31610432007-10-22 11:03:39 +100026#include "hvc_console.h"
27
Amit Shah38edf582010-01-18 19:15:05 +053028/*
29 * This is a global struct for storing common data for all the devices
30 * this driver handles.
31 *
32 * Mainly, it has a linked list for all the consoles in one place so
33 * that callbacks from hvc for get_chars(), put_chars() work properly
34 * across multiple devices and multiple ports per device.
35 */
36struct ports_driver_data {
Rusty Russelld8a02bd2010-01-18 19:15:06 +053037 /*
38 * This is used to keep track of the number of hvc consoles
39 * spawned by this driver. This number is given as the first
40 * argument to hvc_alloc(). To correctly map an initial
41 * console spawned via hvc_instantiate to the console being
42 * hooked up via hvc_alloc, we need to pass the same vtermno.
43 *
44 * We also just assume the first console being initialised was
45 * the first one that got used as the initial console.
46 */
47 unsigned int next_vtermno;
48
Amit Shah38edf582010-01-18 19:15:05 +053049 /* All the console devices handled by this driver */
50 struct list_head consoles;
51};
52static struct ports_driver_data pdrvdata;
53
54DEFINE_SPINLOCK(pdrvdata_lock);
55
Amit Shah4f23c572010-01-18 19:15:09 +053056/* This struct holds information that's relevant only for console ports */
57struct console {
58 /* We'll place all consoles in a list in the pdrvdata struct */
59 struct list_head list;
60
61 /* The hvc device associated with this console port */
62 struct hvc_struct *hvc;
63
64 /*
65 * This number identifies the number that we used to register
66 * with hvc in hvc_instantiate() and hvc_alloc(); this is the
67 * number passed on by the hvc callbacks to us to
68 * differentiate between the other console ports handled by
69 * this driver
70 */
71 u32 vtermno;
72};
73
Amit Shahfdb9a052010-01-18 19:15:01 +053074struct port_buffer {
75 char *buf;
76
77 /* size of the buffer in *buf above */
78 size_t size;
79
80 /* used length of the buffer */
81 size_t len;
82 /* offset in the buf from which to consume data */
83 size_t offset;
84};
85
Amit Shah17634ba2009-12-21 21:03:25 +053086/*
87 * This is a per-device struct that stores data common to all the
88 * ports for that device (vdev->priv).
89 */
90struct ports_device {
91 /*
92 * Workqueue handlers where we process deferred work after
93 * notification
94 */
95 struct work_struct control_work;
96
97 struct list_head ports;
98
99 /* To protect the list of ports */
100 spinlock_t ports_lock;
101
102 /* To protect the vq operations for the control channel */
103 spinlock_t cvq_lock;
104
105 /* The current config space is stored here */
106 struct virtio_console_config config;
107
108 /* The virtio device we're associated with */
109 struct virtio_device *vdev;
110
111 /*
112 * A couple of virtqueues for the control channel: one for
113 * guest->host transfers, one for host->guest transfers
114 */
115 struct virtqueue *c_ivq, *c_ovq;
116
117 /* Array of per-port IO virtqueues */
118 struct virtqueue **in_vqs, **out_vqs;
119};
120
Amit Shah1c85bf32010-01-18 19:15:07 +0530121/* This struct holds the per-port data */
Rusty Russell21206ed2010-01-18 19:15:00 +0530122struct port {
Amit Shah17634ba2009-12-21 21:03:25 +0530123 /* Next port in the list, head is in the ports_device */
124 struct list_head list;
125
Amit Shah1c85bf32010-01-18 19:15:07 +0530126 /* Pointer to the parent virtio_console device */
127 struct ports_device *portdev;
Amit Shahfdb9a052010-01-18 19:15:01 +0530128
129 /* The current buffer from which data has to be fed to readers */
130 struct port_buffer *inbuf;
Rusty Russell31610432007-10-22 11:03:39 +1000131
Amit Shah203baab2010-01-18 19:15:12 +0530132 /*
133 * To protect the operations on the in_vq associated with this
134 * port. Has to be a spinlock because it can be called from
135 * interrupt context (get_char()).
136 */
137 spinlock_t inbuf_lock;
138
Amit Shah1c85bf32010-01-18 19:15:07 +0530139 /* The IO vqs for this port */
140 struct virtqueue *in_vq, *out_vq;
141
Amit Shah4f23c572010-01-18 19:15:09 +0530142 /*
143 * The entries in this struct will be valid if this port is
144 * hooked up to an hvc console
145 */
146 struct console cons;
Amit Shah17634ba2009-12-21 21:03:25 +0530147
148 /* The 'id' to identify the port with the Host */
149 u32 id;
Rusty Russell21206ed2010-01-18 19:15:00 +0530150};
Rusty Russell31610432007-10-22 11:03:39 +1000151
Rusty Russell971f3392010-01-18 19:14:56 +0530152/* This is the very early arch-specified put chars function. */
153static int (*early_put_chars)(u32, const char *, int);
154
Amit Shah38edf582010-01-18 19:15:05 +0530155static struct port *find_port_by_vtermno(u32 vtermno)
156{
157 struct port *port;
Amit Shah4f23c572010-01-18 19:15:09 +0530158 struct console *cons;
Amit Shah38edf582010-01-18 19:15:05 +0530159 unsigned long flags;
160
161 spin_lock_irqsave(&pdrvdata_lock, flags);
Amit Shah4f23c572010-01-18 19:15:09 +0530162 list_for_each_entry(cons, &pdrvdata.consoles, list) {
163 if (cons->vtermno == vtermno) {
164 port = container_of(cons, struct port, cons);
Amit Shah38edf582010-01-18 19:15:05 +0530165 goto out;
Amit Shah4f23c572010-01-18 19:15:09 +0530166 }
Amit Shah38edf582010-01-18 19:15:05 +0530167 }
168 port = NULL;
169out:
170 spin_unlock_irqrestore(&pdrvdata_lock, flags);
171 return port;
172}
173
Amit Shah17634ba2009-12-21 21:03:25 +0530174static struct port *find_port_by_id(struct ports_device *portdev, u32 id)
175{
176 struct port *port;
177 unsigned long flags;
178
179 spin_lock_irqsave(&portdev->ports_lock, flags);
180 list_for_each_entry(port, &portdev->ports, list)
181 if (port->id == id)
182 goto out;
183 port = NULL;
184out:
185 spin_unlock_irqrestore(&portdev->ports_lock, flags);
186
187 return port;
188}
189
Amit Shah203baab2010-01-18 19:15:12 +0530190static struct port *find_port_by_vq(struct ports_device *portdev,
191 struct virtqueue *vq)
192{
193 struct port *port;
Amit Shah203baab2010-01-18 19:15:12 +0530194 unsigned long flags;
195
Amit Shah17634ba2009-12-21 21:03:25 +0530196 spin_lock_irqsave(&portdev->ports_lock, flags);
197 list_for_each_entry(port, &portdev->ports, list)
Amit Shah203baab2010-01-18 19:15:12 +0530198 if (port->in_vq == vq || port->out_vq == vq)
199 goto out;
Amit Shah203baab2010-01-18 19:15:12 +0530200 port = NULL;
201out:
Amit Shah17634ba2009-12-21 21:03:25 +0530202 spin_unlock_irqrestore(&portdev->ports_lock, flags);
Amit Shah203baab2010-01-18 19:15:12 +0530203 return port;
204}
205
Amit Shah17634ba2009-12-21 21:03:25 +0530206static bool is_console_port(struct port *port)
207{
208 if (port->cons.hvc)
209 return true;
210 return false;
211}
212
213static inline bool use_multiport(struct ports_device *portdev)
214{
215 /*
216 * This condition can be true when put_chars is called from
217 * early_init
218 */
219 if (!portdev->vdev)
220 return 0;
221 return portdev->vdev->features[0] & (1 << VIRTIO_CONSOLE_F_MULTIPORT);
222}
223
Amit Shahfdb9a052010-01-18 19:15:01 +0530224static void free_buf(struct port_buffer *buf)
225{
226 kfree(buf->buf);
227 kfree(buf);
228}
229
230static struct port_buffer *alloc_buf(size_t buf_size)
231{
232 struct port_buffer *buf;
233
234 buf = kmalloc(sizeof(*buf), GFP_KERNEL);
235 if (!buf)
236 goto fail;
237 buf->buf = kzalloc(buf_size, GFP_KERNEL);
238 if (!buf->buf)
239 goto free_buf;
240 buf->len = 0;
241 buf->offset = 0;
242 buf->size = buf_size;
243 return buf;
244
245free_buf:
246 kfree(buf);
247fail:
248 return NULL;
249}
250
Amit Shaha3cde442010-01-18 19:15:03 +0530251/* Callers should take appropriate locks */
252static void *get_inbuf(struct port *port)
253{
254 struct port_buffer *buf;
255 struct virtqueue *vq;
256 unsigned int len;
257
258 vq = port->in_vq;
259 buf = vq->vq_ops->get_buf(vq, &len);
260 if (buf) {
261 buf->len = len;
262 buf->offset = 0;
263 }
264 return buf;
265}
266
Rusty Russella23ea922010-01-18 19:14:55 +0530267/*
Amit Shahe27b5192010-01-18 19:15:02 +0530268 * Create a scatter-gather list representing our input buffer and put
269 * it in the queue.
270 *
271 * Callers should take appropriate locks.
272 */
Amit Shah203baab2010-01-18 19:15:12 +0530273static int add_inbuf(struct virtqueue *vq, struct port_buffer *buf)
Amit Shahe27b5192010-01-18 19:15:02 +0530274{
275 struct scatterlist sg[1];
Amit Shah203baab2010-01-18 19:15:12 +0530276 int ret;
Amit Shah1c85bf32010-01-18 19:15:07 +0530277
Amit Shahe27b5192010-01-18 19:15:02 +0530278 sg_init_one(sg, buf->buf, buf->size);
279
Amit Shah203baab2010-01-18 19:15:12 +0530280 ret = vq->vq_ops->add_buf(vq, sg, 0, 1, buf);
Amit Shahe27b5192010-01-18 19:15:02 +0530281 vq->vq_ops->kick(vq);
Amit Shah203baab2010-01-18 19:15:12 +0530282 return ret;
283}
284
285static bool port_has_data(struct port *port)
286{
287 unsigned long flags;
288 bool ret;
289
290 ret = false;
291 spin_lock_irqsave(&port->inbuf_lock, flags);
292 if (port->inbuf)
293 ret = true;
294 spin_unlock_irqrestore(&port->inbuf_lock, flags);
295
296 return ret;
297}
298
Amit Shah17634ba2009-12-21 21:03:25 +0530299static ssize_t send_control_msg(struct port *port, unsigned int event,
300 unsigned int value)
301{
302 struct scatterlist sg[1];
303 struct virtio_console_control cpkt;
304 struct virtqueue *vq;
305 int len;
306
307 if (!use_multiport(port->portdev))
308 return 0;
309
310 cpkt.id = port->id;
311 cpkt.event = event;
312 cpkt.value = value;
313
314 vq = port->portdev->c_ovq;
315
316 sg_init_one(sg, &cpkt, sizeof(cpkt));
317 if (vq->vq_ops->add_buf(vq, sg, 1, 0, &cpkt) >= 0) {
318 vq->vq_ops->kick(vq);
319 while (!vq->vq_ops->get_buf(vq, &len))
320 cpu_relax();
321 }
322 return 0;
323}
324
Amit Shahf997f00b2009-12-21 17:28:51 +0530325static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count)
326{
327 struct scatterlist sg[1];
328 struct virtqueue *out_vq;
329 ssize_t ret;
330 unsigned int len;
331
332 out_vq = port->out_vq;
333
334 sg_init_one(sg, in_buf, in_count);
335 ret = out_vq->vq_ops->add_buf(out_vq, sg, 1, 0, in_buf);
336
337 /* Tell Host to go! */
338 out_vq->vq_ops->kick(out_vq);
339
340 if (ret < 0) {
341 len = 0;
342 goto fail;
343 }
344
345 /*
346 * Wait till the host acknowledges it pushed out the data we
347 * sent. Also ensure we return to userspace the number of
348 * bytes that were successfully consumed by the host.
349 */
350 while (!out_vq->vq_ops->get_buf(out_vq, &len))
351 cpu_relax();
352fail:
353 /* We're expected to return the amount of data we wrote */
354 return len;
355}
356
Amit Shah203baab2010-01-18 19:15:12 +0530357/*
358 * Give out the data that's requested from the buffer that we have
359 * queued up.
360 */
Amit Shahb766cee2009-12-21 21:26:45 +0530361static ssize_t fill_readbuf(struct port *port, char *out_buf, size_t out_count,
362 bool to_user)
Amit Shah203baab2010-01-18 19:15:12 +0530363{
364 struct port_buffer *buf;
365 unsigned long flags;
366
367 if (!out_count || !port_has_data(port))
368 return 0;
369
370 buf = port->inbuf;
Amit Shahb766cee2009-12-21 21:26:45 +0530371 out_count = min(out_count, buf->len - buf->offset);
Amit Shah203baab2010-01-18 19:15:12 +0530372
Amit Shahb766cee2009-12-21 21:26:45 +0530373 if (to_user) {
374 ssize_t ret;
Amit Shah203baab2010-01-18 19:15:12 +0530375
Amit Shahb766cee2009-12-21 21:26:45 +0530376 ret = copy_to_user(out_buf, buf->buf + buf->offset, out_count);
377 if (ret)
378 return -EFAULT;
379 } else {
380 memcpy(out_buf, buf->buf + buf->offset, out_count);
381 }
382
Amit Shah203baab2010-01-18 19:15:12 +0530383 buf->offset += out_count;
384
385 if (buf->offset == buf->len) {
386 /*
387 * We're done using all the data in this buffer.
388 * Re-queue so that the Host can send us more data.
389 */
390 spin_lock_irqsave(&port->inbuf_lock, flags);
391 port->inbuf = NULL;
392
393 if (add_inbuf(port->in_vq, buf) < 0)
394 dev_warn(&port->portdev->vdev->dev, "failed add_buf\n");
395
396 spin_unlock_irqrestore(&port->inbuf_lock, flags);
397 }
Amit Shahb766cee2009-12-21 21:26:45 +0530398 /* Return the number of bytes actually copied */
Amit Shah203baab2010-01-18 19:15:12 +0530399 return out_count;
Amit Shahe27b5192010-01-18 19:15:02 +0530400}
401
402/*
Rusty Russella23ea922010-01-18 19:14:55 +0530403 * The put_chars() callback is pretty straightforward.
Rusty Russell31610432007-10-22 11:03:39 +1000404 *
Rusty Russella23ea922010-01-18 19:14:55 +0530405 * We turn the characters into a scatter-gather list, add it to the
406 * output queue and then kick the Host. Then we sit here waiting for
407 * it to finish: inefficient in theory, but in practice
408 * implementations will do it immediately (lguest's Launcher does).
409 */
Rusty Russell31610432007-10-22 11:03:39 +1000410static int put_chars(u32 vtermno, const char *buf, int count)
411{
Rusty Russell21206ed2010-01-18 19:15:00 +0530412 struct port *port;
Amit Shah38edf582010-01-18 19:15:05 +0530413
414 port = find_port_by_vtermno(vtermno);
415 if (!port)
416 return 0;
Rusty Russell31610432007-10-22 11:03:39 +1000417
Rusty Russell971f3392010-01-18 19:14:56 +0530418 if (unlikely(early_put_chars))
419 return early_put_chars(vtermno, buf, count);
420
Amit Shahf997f00b2009-12-21 17:28:51 +0530421 return send_buf(port, (void *)buf, count);
Rusty Russell31610432007-10-22 11:03:39 +1000422}
423
Rusty Russella23ea922010-01-18 19:14:55 +0530424/*
Rusty Russella23ea922010-01-18 19:14:55 +0530425 * get_chars() is the callback from the hvc_console infrastructure
426 * when an interrupt is received.
Rusty Russell31610432007-10-22 11:03:39 +1000427 *
Amit Shah203baab2010-01-18 19:15:12 +0530428 * We call out to fill_readbuf that gets us the required data from the
429 * buffers that are queued up.
Rusty Russella23ea922010-01-18 19:14:55 +0530430 */
Rusty Russell31610432007-10-22 11:03:39 +1000431static int get_chars(u32 vtermno, char *buf, int count)
432{
Rusty Russell21206ed2010-01-18 19:15:00 +0530433 struct port *port;
Rusty Russell31610432007-10-22 11:03:39 +1000434
Amit Shah38edf582010-01-18 19:15:05 +0530435 port = find_port_by_vtermno(vtermno);
436 if (!port)
437 return 0;
Rusty Russell21206ed2010-01-18 19:15:00 +0530438
439 /* If we don't have an input queue yet, we can't get input. */
440 BUG_ON(!port->in_vq);
441
Amit Shahb766cee2009-12-21 21:26:45 +0530442 return fill_readbuf(port, buf, count, false);
Rusty Russell31610432007-10-22 11:03:39 +1000443}
Rusty Russell31610432007-10-22 11:03:39 +1000444
Amit Shahcb06e362010-01-18 19:15:08 +0530445static void resize_console(struct port *port)
Christian Borntraegerc2983452008-11-25 13:36:26 +0100446{
Amit Shahcb06e362010-01-18 19:15:08 +0530447 struct virtio_device *vdev;
Christian Borntraegerc2983452008-11-25 13:36:26 +0100448 struct winsize ws;
449
Amit Shahcb06e362010-01-18 19:15:08 +0530450 vdev = port->portdev->vdev;
451 if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_SIZE)) {
452 vdev->config->get(vdev,
453 offsetof(struct virtio_console_config, cols),
454 &ws.ws_col, sizeof(u16));
455 vdev->config->get(vdev,
456 offsetof(struct virtio_console_config, rows),
457 &ws.ws_row, sizeof(u16));
Amit Shah4f23c572010-01-18 19:15:09 +0530458 hvc_resize(port->cons.hvc, ws);
Christian Borntraegerc2983452008-11-25 13:36:26 +0100459 }
460}
461
Amit Shahcb06e362010-01-18 19:15:08 +0530462static void virtcons_apply_config(struct virtio_device *vdev)
463{
464 resize_console(find_port_by_vtermno(0));
465}
466
Amit Shah38edf582010-01-18 19:15:05 +0530467/* We set the configuration at this point, since we now have a tty */
Christian Borntraeger91fcad12008-06-20 15:24:15 +0200468static int notifier_add_vio(struct hvc_struct *hp, int data)
469{
Amit Shah38edf582010-01-18 19:15:05 +0530470 struct port *port;
471
472 port = find_port_by_vtermno(hp->vtermno);
473 if (!port)
474 return -EINVAL;
475
Christian Borntraeger91fcad12008-06-20 15:24:15 +0200476 hp->irq_requested = 1;
Amit Shahcb06e362010-01-18 19:15:08 +0530477 resize_console(port);
Christian Borntraegerc2983452008-11-25 13:36:26 +0100478
Christian Borntraeger91fcad12008-06-20 15:24:15 +0200479 return 0;
480}
481
482static void notifier_del_vio(struct hvc_struct *hp, int data)
483{
484 hp->irq_requested = 0;
485}
486
Amit Shah17634ba2009-12-21 21:03:25 +0530487/* The operations for console ports. */
Rusty Russell1dff3992009-11-28 12:20:26 +0530488static const struct hv_ops hv_ops = {
Rusty Russell971f3392010-01-18 19:14:56 +0530489 .get_chars = get_chars,
490 .put_chars = put_chars,
491 .notifier_add = notifier_add_vio,
492 .notifier_del = notifier_del_vio,
493 .notifier_hangup = notifier_del_vio,
494};
495
496/*
497 * Console drivers are initialized very early so boot messages can go
498 * out, so we do things slightly differently from the generic virtio
499 * initialization of the net and block drivers.
500 *
501 * At this stage, the console is output-only. It's too early to set
502 * up a virtqueue, so we let the drivers do some boutique early-output
503 * thing.
504 */
505int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int))
506{
507 early_put_chars = put_chars;
508 return hvc_instantiate(0, 0, &hv_ops);
509}
510
Amit Shah17634ba2009-12-21 21:03:25 +0530511int init_port_console(struct port *port)
Amit Shahcfa6d372010-01-18 19:15:10 +0530512{
513 int ret;
514
515 /*
516 * The Host's telling us this port is a console port. Hook it
517 * up with an hvc console.
518 *
519 * To set up and manage our virtual console, we call
520 * hvc_alloc().
521 *
522 * The first argument of hvc_alloc() is the virtual console
523 * number. The second argument is the parameter for the
524 * notification mechanism (like irq number). We currently
525 * leave this as zero, virtqueues have implicit notifications.
526 *
527 * The third argument is a "struct hv_ops" containing the
528 * put_chars() get_chars(), notifier_add() and notifier_del()
529 * pointers. The final argument is the output buffer size: we
530 * can do any size, so we put PAGE_SIZE here.
531 */
532 port->cons.vtermno = pdrvdata.next_vtermno;
533
534 port->cons.hvc = hvc_alloc(port->cons.vtermno, 0, &hv_ops, PAGE_SIZE);
535 if (IS_ERR(port->cons.hvc)) {
536 ret = PTR_ERR(port->cons.hvc);
537 port->cons.hvc = NULL;
538 return ret;
539 }
540 spin_lock_irq(&pdrvdata_lock);
541 pdrvdata.next_vtermno++;
542 list_add_tail(&port->cons.list, &pdrvdata.consoles);
543 spin_unlock_irq(&pdrvdata_lock);
544
545 return 0;
546}
547
Amit Shah17634ba2009-12-21 21:03:25 +0530548/* Any private messages that the Host and Guest want to share */
549static void handle_control_message(struct ports_device *portdev,
550 struct port_buffer *buf)
551{
552 struct virtio_console_control *cpkt;
553 struct port *port;
554
555 cpkt = (struct virtio_console_control *)(buf->buf + buf->offset);
556
557 port = find_port_by_id(portdev, cpkt->id);
558 if (!port) {
559 /* No valid header at start of buffer. Drop it. */
560 dev_dbg(&portdev->vdev->dev,
561 "Invalid index %u in control packet\n", cpkt->id);
562 return;
563 }
564
565 switch (cpkt->event) {
566 case VIRTIO_CONSOLE_CONSOLE_PORT:
567 if (!cpkt->value)
568 break;
569 if (is_console_port(port))
570 break;
571
572 init_port_console(port);
573 /*
574 * Could remove the port here in case init fails - but
575 * have to notify the host first.
576 */
577 break;
578 case VIRTIO_CONSOLE_RESIZE:
579 if (!is_console_port(port))
580 break;
581 port->cons.hvc->irq_requested = 1;
582 resize_console(port);
583 break;
584 }
585}
586
587static void control_work_handler(struct work_struct *work)
588{
589 struct ports_device *portdev;
590 struct virtqueue *vq;
591 struct port_buffer *buf;
592 unsigned int len;
593
594 portdev = container_of(work, struct ports_device, control_work);
595 vq = portdev->c_ivq;
596
597 spin_lock(&portdev->cvq_lock);
598 while ((buf = vq->vq_ops->get_buf(vq, &len))) {
599 spin_unlock(&portdev->cvq_lock);
600
601 buf->len = len;
602 buf->offset = 0;
603
604 handle_control_message(portdev, buf);
605
606 spin_lock(&portdev->cvq_lock);
607 if (add_inbuf(portdev->c_ivq, buf) < 0) {
608 dev_warn(&portdev->vdev->dev,
609 "Error adding buffer to queue\n");
610 free_buf(buf);
611 }
612 }
613 spin_unlock(&portdev->cvq_lock);
614}
615
616static void in_intr(struct virtqueue *vq)
617{
618 struct port *port;
619 unsigned long flags;
620
621 port = find_port_by_vq(vq->vdev->priv, vq);
622 if (!port)
623 return;
624
625 spin_lock_irqsave(&port->inbuf_lock, flags);
626 port->inbuf = get_inbuf(port);
627
628 spin_unlock_irqrestore(&port->inbuf_lock, flags);
629
630 if (is_console_port(port) && hvc_poll(port->cons.hvc))
631 hvc_kick();
632}
633
634static void control_intr(struct virtqueue *vq)
635{
636 struct ports_device *portdev;
637
638 portdev = vq->vdev->priv;
639 schedule_work(&portdev->control_work);
640}
641
642static void fill_queue(struct virtqueue *vq, spinlock_t *lock)
643{
644 struct port_buffer *buf;
645 int ret;
646
647 do {
648 buf = alloc_buf(PAGE_SIZE);
649 if (!buf)
650 break;
651
652 spin_lock_irq(lock);
653 ret = add_inbuf(vq, buf);
654 if (ret < 0) {
655 spin_unlock_irq(lock);
656 free_buf(buf);
657 break;
658 }
659 spin_unlock_irq(lock);
660 } while (ret > 0);
661}
662
663static int add_port(struct ports_device *portdev, u32 id)
Rusty Russelld8a02bd2010-01-18 19:15:06 +0530664{
665 struct port *port;
Amit Shah203baab2010-01-18 19:15:12 +0530666 struct port_buffer *inbuf;
Rusty Russell31610432007-10-22 11:03:39 +1000667 int err;
Rusty Russell31610432007-10-22 11:03:39 +1000668
Amit Shah1c85bf32010-01-18 19:15:07 +0530669 port = kmalloc(sizeof(*port), GFP_KERNEL);
Rusty Russelld8a02bd2010-01-18 19:15:06 +0530670 if (!port) {
671 err = -ENOMEM;
672 goto fail;
Amit Shahf5508042010-01-18 19:14:59 +0530673 }
Rusty Russell73954482010-01-18 19:15:04 +0530674
Amit Shah1c85bf32010-01-18 19:15:07 +0530675 port->portdev = portdev;
Amit Shah17634ba2009-12-21 21:03:25 +0530676 port->id = id;
Amit Shah203baab2010-01-18 19:15:12 +0530677
678 port->inbuf = NULL;
Amit Shah17634ba2009-12-21 21:03:25 +0530679 port->cons.hvc = NULL;
Amit Shah203baab2010-01-18 19:15:12 +0530680
Amit Shah17634ba2009-12-21 21:03:25 +0530681 port->in_vq = portdev->in_vqs[port->id];
682 port->out_vq = portdev->out_vqs[port->id];
Rusty Russell31610432007-10-22 11:03:39 +1000683
Amit Shah203baab2010-01-18 19:15:12 +0530684 spin_lock_init(&port->inbuf_lock);
685
686 inbuf = alloc_buf(PAGE_SIZE);
687 if (!inbuf) {
Amit Shah1c85bf32010-01-18 19:15:07 +0530688 err = -ENOMEM;
689 goto free_port;
690 }
Rusty Russell31610432007-10-22 11:03:39 +1000691
Amit Shah203baab2010-01-18 19:15:12 +0530692 /* Register the input buffer the first time. */
693 add_inbuf(port->in_vq, inbuf);
694
Amit Shah17634ba2009-12-21 21:03:25 +0530695 /*
696 * If we're not using multiport support, this has to be a console port
697 */
698 if (!use_multiport(port->portdev)) {
699 err = init_port_console(port);
700 if (err)
701 goto free_inbuf;
702 }
703
704 spin_lock_irq(&portdev->ports_lock);
705 list_add_tail(&port->list, &port->portdev->ports);
706 spin_unlock_irq(&portdev->ports_lock);
707
708 /*
709 * Tell the Host we're set so that it can send us various
710 * configuration parameters for this port (eg, port name,
711 * caching, whether this is a console port, etc.)
712 */
713 send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1);
Amit Shah38edf582010-01-18 19:15:05 +0530714
Amit Shah1c85bf32010-01-18 19:15:07 +0530715 return 0;
716
717free_inbuf:
Amit Shah203baab2010-01-18 19:15:12 +0530718 free_buf(inbuf);
Amit Shah1c85bf32010-01-18 19:15:07 +0530719free_port:
720 kfree(port);
721fail:
722 return err;
723}
724
Amit Shah2658a792010-01-18 19:15:11 +0530725static int init_vqs(struct ports_device *portdev)
726{
727 vq_callback_t **io_callbacks;
728 char **io_names;
729 struct virtqueue **vqs;
Amit Shah17634ba2009-12-21 21:03:25 +0530730 u32 i, j, nr_ports, nr_queues;
Amit Shah2658a792010-01-18 19:15:11 +0530731 int err;
732
Amit Shah17634ba2009-12-21 21:03:25 +0530733 nr_ports = portdev->config.max_nr_ports;
734 nr_queues = use_multiport(portdev) ? (nr_ports + 1) * 2 : 2;
Amit Shah2658a792010-01-18 19:15:11 +0530735
736 vqs = kmalloc(nr_queues * sizeof(struct virtqueue *), GFP_KERNEL);
737 if (!vqs) {
738 err = -ENOMEM;
739 goto fail;
740 }
741 io_callbacks = kmalloc(nr_queues * sizeof(vq_callback_t *), GFP_KERNEL);
742 if (!io_callbacks) {
743 err = -ENOMEM;
744 goto free_vqs;
745 }
746 io_names = kmalloc(nr_queues * sizeof(char *), GFP_KERNEL);
747 if (!io_names) {
748 err = -ENOMEM;
749 goto free_callbacks;
750 }
751 portdev->in_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *),
752 GFP_KERNEL);
753 if (!portdev->in_vqs) {
754 err = -ENOMEM;
755 goto free_names;
756 }
757 portdev->out_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *),
758 GFP_KERNEL);
759 if (!portdev->out_vqs) {
760 err = -ENOMEM;
761 goto free_invqs;
762 }
763
Amit Shah17634ba2009-12-21 21:03:25 +0530764 /*
765 * For backward compat (newer host but older guest), the host
766 * spawns a console port first and also inits the vqs for port
767 * 0 before others.
768 */
769 j = 0;
770 io_callbacks[j] = in_intr;
771 io_callbacks[j + 1] = NULL;
772 io_names[j] = "input";
773 io_names[j + 1] = "output";
774 j += 2;
Amit Shah2658a792010-01-18 19:15:11 +0530775
Amit Shah17634ba2009-12-21 21:03:25 +0530776 if (use_multiport(portdev)) {
777 io_callbacks[j] = control_intr;
778 io_callbacks[j + 1] = NULL;
779 io_names[j] = "control-i";
780 io_names[j + 1] = "control-o";
781
782 for (i = 1; i < nr_ports; i++) {
783 j += 2;
784 io_callbacks[j] = in_intr;
785 io_callbacks[j + 1] = NULL;
786 io_names[j] = "input";
787 io_names[j + 1] = "output";
788 }
789 }
Amit Shah2658a792010-01-18 19:15:11 +0530790 /* Find the queues. */
791 err = portdev->vdev->config->find_vqs(portdev->vdev, nr_queues, vqs,
792 io_callbacks,
793 (const char **)io_names);
794 if (err)
795 goto free_outvqs;
796
Amit Shah17634ba2009-12-21 21:03:25 +0530797 j = 0;
Amit Shah2658a792010-01-18 19:15:11 +0530798 portdev->in_vqs[0] = vqs[0];
799 portdev->out_vqs[0] = vqs[1];
Amit Shah17634ba2009-12-21 21:03:25 +0530800 j += 2;
801 if (use_multiport(portdev)) {
802 portdev->c_ivq = vqs[j];
803 portdev->c_ovq = vqs[j + 1];
Amit Shah2658a792010-01-18 19:15:11 +0530804
Amit Shah17634ba2009-12-21 21:03:25 +0530805 for (i = 1; i < nr_ports; i++) {
806 j += 2;
807 portdev->in_vqs[i] = vqs[j];
808 portdev->out_vqs[i] = vqs[j + 1];
809 }
810 }
Amit Shah2658a792010-01-18 19:15:11 +0530811 kfree(io_callbacks);
812 kfree(io_names);
813 kfree(vqs);
814
815 return 0;
816
817free_names:
818 kfree(io_names);
819free_callbacks:
820 kfree(io_callbacks);
821free_outvqs:
822 kfree(portdev->out_vqs);
823free_invqs:
824 kfree(portdev->in_vqs);
825free_vqs:
826 kfree(vqs);
827fail:
828 return err;
829}
830
Amit Shah1c85bf32010-01-18 19:15:07 +0530831/*
832 * Once we're further in boot, we get probed like any other virtio
833 * device.
Amit Shah17634ba2009-12-21 21:03:25 +0530834 *
835 * If the host also supports multiple console ports, we check the
836 * config space to see how many ports the host has spawned. We
837 * initialize each port found.
Amit Shah1c85bf32010-01-18 19:15:07 +0530838 */
839static int __devinit virtcons_probe(struct virtio_device *vdev)
840{
Amit Shah1c85bf32010-01-18 19:15:07 +0530841 struct ports_device *portdev;
Amit Shah17634ba2009-12-21 21:03:25 +0530842 u32 i;
Amit Shah1c85bf32010-01-18 19:15:07 +0530843 int err;
Amit Shah17634ba2009-12-21 21:03:25 +0530844 bool multiport;
Amit Shah1c85bf32010-01-18 19:15:07 +0530845
846 portdev = kmalloc(sizeof(*portdev), GFP_KERNEL);
847 if (!portdev) {
848 err = -ENOMEM;
849 goto fail;
850 }
851
852 /* Attach this portdev to this virtio_device, and vice-versa. */
853 portdev->vdev = vdev;
854 vdev->priv = portdev;
855
Amit Shah17634ba2009-12-21 21:03:25 +0530856 multiport = false;
857 portdev->config.nr_ports = 1;
858 portdev->config.max_nr_ports = 1;
859 if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT)) {
860 multiport = true;
861 vdev->features[0] |= 1 << VIRTIO_CONSOLE_F_MULTIPORT;
862
863 vdev->config->get(vdev, offsetof(struct virtio_console_config,
864 nr_ports),
865 &portdev->config.nr_ports,
866 sizeof(portdev->config.nr_ports));
867 vdev->config->get(vdev, offsetof(struct virtio_console_config,
868 max_nr_ports),
869 &portdev->config.max_nr_ports,
870 sizeof(portdev->config.max_nr_ports));
871 if (portdev->config.nr_ports > portdev->config.max_nr_ports) {
872 dev_warn(&vdev->dev,
873 "More ports (%u) specified than allowed (%u). Will init %u ports.",
874 portdev->config.nr_ports,
875 portdev->config.max_nr_ports,
876 portdev->config.max_nr_ports);
877
878 portdev->config.nr_ports = portdev->config.max_nr_ports;
879 }
880 }
881
882 /* Let the Host know we support multiple ports.*/
883 vdev->config->finalize_features(vdev);
884
Amit Shah2658a792010-01-18 19:15:11 +0530885 err = init_vqs(portdev);
886 if (err < 0) {
887 dev_err(&vdev->dev, "Error %d initializing vqs\n", err);
Amit Shah1c85bf32010-01-18 19:15:07 +0530888 goto free;
Amit Shah2658a792010-01-18 19:15:11 +0530889 }
Amit Shah1c85bf32010-01-18 19:15:07 +0530890
Amit Shah17634ba2009-12-21 21:03:25 +0530891 spin_lock_init(&portdev->ports_lock);
892 INIT_LIST_HEAD(&portdev->ports);
893
894 if (multiport) {
895 spin_lock_init(&portdev->cvq_lock);
896 INIT_WORK(&portdev->control_work, &control_work_handler);
897
898 fill_queue(portdev->c_ivq, &portdev->cvq_lock);
899 }
900
901 for (i = 0; i < portdev->config.nr_ports; i++)
902 add_port(portdev, i);
Amit Shah1c85bf32010-01-18 19:15:07 +0530903
Rusty Russell971f3392010-01-18 19:14:56 +0530904 /* Start using the new console output. */
905 early_put_chars = NULL;
Rusty Russell31610432007-10-22 11:03:39 +1000906 return 0;
907
Michael S. Tsirkind2a7ddd2009-06-12 22:16:36 -0600908free_vqs:
909 vdev->config->del_vqs(vdev);
Amit Shah2658a792010-01-18 19:15:11 +0530910 kfree(portdev->in_vqs);
911 kfree(portdev->out_vqs);
Rusty Russell31610432007-10-22 11:03:39 +1000912free:
Amit Shah1c85bf32010-01-18 19:15:07 +0530913 kfree(portdev);
Rusty Russell31610432007-10-22 11:03:39 +1000914fail:
915 return err;
916}
917
918static struct virtio_device_id id_table[] = {
919 { VIRTIO_ID_CONSOLE, VIRTIO_DEV_ANY_ID },
920 { 0 },
921};
922
Christian Borntraegerc2983452008-11-25 13:36:26 +0100923static unsigned int features[] = {
924 VIRTIO_CONSOLE_F_SIZE,
Amit Shah17634ba2009-12-21 21:03:25 +0530925 VIRTIO_CONSOLE_F_MULTIPORT,
Christian Borntraegerc2983452008-11-25 13:36:26 +0100926};
927
Rusty Russell31610432007-10-22 11:03:39 +1000928static struct virtio_driver virtio_console = {
Christian Borntraegerc2983452008-11-25 13:36:26 +0100929 .feature_table = features,
930 .feature_table_size = ARRAY_SIZE(features),
Rusty Russell31610432007-10-22 11:03:39 +1000931 .driver.name = KBUILD_MODNAME,
932 .driver.owner = THIS_MODULE,
933 .id_table = id_table,
934 .probe = virtcons_probe,
Christian Borntraegerc2983452008-11-25 13:36:26 +0100935 .config_changed = virtcons_apply_config,
Rusty Russell31610432007-10-22 11:03:39 +1000936};
937
938static int __init init(void)
939{
Amit Shah38edf582010-01-18 19:15:05 +0530940 INIT_LIST_HEAD(&pdrvdata.consoles);
941
Rusty Russell31610432007-10-22 11:03:39 +1000942 return register_virtio_driver(&virtio_console);
943}
944module_init(init);
945
946MODULE_DEVICE_TABLE(virtio, id_table);
947MODULE_DESCRIPTION("Virtio console driver");
948MODULE_LICENSE("GPL");