diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 20:22:52 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 20:22:52 -0400 |
commit | 1756ac3d3c41341297ea25b818b7fce505bb2a9a (patch) | |
tree | 96382220afbb82fd5c576c4c08b3c3e13282851f | |
parent | 98edb6ca4174f17a64890a02f44c211c8b44fb3c (diff) | |
parent | 0643e4c6e4fd67778fa886a89e6ec2320e0ff4d3 (diff) |
Merge branch 'virtio' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus
* 'virtio' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus: (27 commits)
drivers/char: Eliminate use after free
virtio: console: Accept console size along with resize control message
virtio: console: Store each console's size in the console structure
virtio: console: Resize console port 0 on config intr only if multiport is off
virtio: console: Add support for nonblocking write()s
virtio: console: Rename wait_is_over() to will_read_block()
virtio: console: Don't always create a port 0 if using multiport
virtio: console: Use a control message to add ports
virtio: console: Move code around for future patches
virtio: console: Remove config work handler
virtio: console: Don't call hvc_remove() on unplugging console ports
virtio: console: Return -EPIPE to hvc_console if we lost the connection
virtio: console: Let host know of port or device add failures
virtio: console: Add a __send_control_msg() that can send messages without a valid port
virtio: Revert "virtio: disable multiport console support."
virtio: add_buf_gfp
trans_virtio: use virtqueue_xxx wrappers
virtio-rng: use virtqueue_xxx wrappers
virtio_ring: remove a level of indirection
virtio_net: use virtqueue_xxx wrappers
...
Fix up conflicts in drivers/net/virtio_net.c due to new virtqueue_xxx
wrappers changes conflicting with some other cleanups.
-rw-r--r-- | drivers/block/virtio_blk.c | 46 | ||||
-rw-r--r-- | drivers/char/hw_random/virtio-rng.c | 6 | ||||
-rw-r--r-- | drivers/char/virtio_console.c | 700 | ||||
-rw-r--r-- | drivers/net/virtio_net.c | 46 | ||||
-rw-r--r-- | drivers/virtio/virtio_balloon.c | 17 | ||||
-rw-r--r-- | drivers/virtio/virtio_ring.c | 44 | ||||
-rw-r--r-- | include/linux/virtio.h | 55 | ||||
-rw-r--r-- | include/linux/virtio_blk.h | 5 | ||||
-rw-r--r-- | include/linux/virtio_console.h | 25 | ||||
-rw-r--r-- | net/9p/trans_virtio.c | 6 |
10 files changed, 541 insertions, 409 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 2138a7ae050c..83fa09a836ca 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -50,7 +50,7 @@ static void blk_done(struct virtqueue *vq) | |||
50 | unsigned long flags; | 50 | unsigned long flags; |
51 | 51 | ||
52 | spin_lock_irqsave(&vblk->lock, flags); | 52 | spin_lock_irqsave(&vblk->lock, flags); |
53 | while ((vbr = vblk->vq->vq_ops->get_buf(vblk->vq, &len)) != NULL) { | 53 | while ((vbr = virtqueue_get_buf(vblk->vq, &len)) != NULL) { |
54 | int error; | 54 | int error; |
55 | 55 | ||
56 | switch (vbr->status) { | 56 | switch (vbr->status) { |
@@ -70,6 +70,8 @@ static void blk_done(struct virtqueue *vq) | |||
70 | vbr->req->sense_len = vbr->in_hdr.sense_len; | 70 | vbr->req->sense_len = vbr->in_hdr.sense_len; |
71 | vbr->req->errors = vbr->in_hdr.errors; | 71 | vbr->req->errors = vbr->in_hdr.errors; |
72 | } | 72 | } |
73 | if (blk_special_request(vbr->req)) | ||
74 | vbr->req->errors = (error != 0); | ||
73 | 75 | ||
74 | __blk_end_request_all(vbr->req, error); | 76 | __blk_end_request_all(vbr->req, error); |
75 | list_del(&vbr->list); | 77 | list_del(&vbr->list); |
@@ -103,6 +105,11 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, | |||
103 | vbr->out_hdr.sector = 0; | 105 | vbr->out_hdr.sector = 0; |
104 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); | 106 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); |
105 | break; | 107 | break; |
108 | case REQ_TYPE_SPECIAL: | ||
109 | vbr->out_hdr.type = VIRTIO_BLK_T_GET_ID; | ||
110 | vbr->out_hdr.sector = 0; | ||
111 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); | ||
112 | break; | ||
106 | case REQ_TYPE_LINUX_BLOCK: | 113 | case REQ_TYPE_LINUX_BLOCK: |
107 | if (req->cmd[0] == REQ_LB_OP_FLUSH) { | 114 | if (req->cmd[0] == REQ_LB_OP_FLUSH) { |
108 | vbr->out_hdr.type = VIRTIO_BLK_T_FLUSH; | 115 | vbr->out_hdr.type = VIRTIO_BLK_T_FLUSH; |
@@ -151,7 +158,7 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, | |||
151 | } | 158 | } |
152 | } | 159 | } |
153 | 160 | ||
154 | if (vblk->vq->vq_ops->add_buf(vblk->vq, vblk->sg, out, in, vbr) < 0) { | 161 | if (virtqueue_add_buf(vblk->vq, vblk->sg, out, in, vbr) < 0) { |
155 | mempool_free(vbr, vblk->pool); | 162 | mempool_free(vbr, vblk->pool); |
156 | return false; | 163 | return false; |
157 | } | 164 | } |
@@ -180,7 +187,7 @@ static void do_virtblk_request(struct request_queue *q) | |||
180 | } | 187 | } |
181 | 188 | ||
182 | if (issued) | 189 | if (issued) |
183 | vblk->vq->vq_ops->kick(vblk->vq); | 190 | virtqueue_kick(vblk->vq); |
184 | } | 191 | } |
185 | 192 | ||
186 | static void virtblk_prepare_flush(struct request_queue *q, struct request *req) | 193 | static void virtblk_prepare_flush(struct request_queue *q, struct request *req) |
@@ -189,12 +196,45 @@ static void virtblk_prepare_flush(struct request_queue *q, struct request *req) | |||
189 | req->cmd[0] = REQ_LB_OP_FLUSH; | 196 | req->cmd[0] = REQ_LB_OP_FLUSH; |
190 | } | 197 | } |
191 | 198 | ||
199 | /* return id (s/n) string for *disk to *id_str | ||
200 | */ | ||
201 | static int virtblk_get_id(struct gendisk *disk, char *id_str) | ||
202 | { | ||
203 | struct virtio_blk *vblk = disk->private_data; | ||
204 | struct request *req; | ||
205 | struct bio *bio; | ||
206 | |||
207 | bio = bio_map_kern(vblk->disk->queue, id_str, VIRTIO_BLK_ID_BYTES, | ||
208 | GFP_KERNEL); | ||
209 | if (IS_ERR(bio)) | ||
210 | return PTR_ERR(bio); | ||
211 | |||
212 | req = blk_make_request(vblk->disk->queue, bio, GFP_KERNEL); | ||
213 | if (IS_ERR(req)) { | ||
214 | bio_put(bio); | ||
215 | return PTR_ERR(req); | ||
216 | } | ||
217 | |||
218 | req->cmd_type = REQ_TYPE_SPECIAL; | ||
219 | return blk_execute_rq(vblk->disk->queue, vblk->disk, req, false); | ||
220 | } | ||
221 | |||
192 | static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, | 222 | static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, |
193 | unsigned cmd, unsigned long data) | 223 | unsigned cmd, unsigned long data) |
194 | { | 224 | { |
195 | struct gendisk *disk = bdev->bd_disk; | 225 | struct gendisk *disk = bdev->bd_disk; |
196 | struct virtio_blk *vblk = disk->private_data; | 226 | struct virtio_blk *vblk = disk->private_data; |
197 | 227 | ||
228 | if (cmd == 0x56424944) { /* 'VBID' */ | ||
229 | void __user *usr_data = (void __user *)data; | ||
230 | char id_str[VIRTIO_BLK_ID_BYTES]; | ||
231 | int err; | ||
232 | |||
233 | err = virtblk_get_id(disk, id_str); | ||
234 | if (!err && copy_to_user(usr_data, id_str, VIRTIO_BLK_ID_BYTES)) | ||
235 | err = -EFAULT; | ||
236 | return err; | ||
237 | } | ||
198 | /* | 238 | /* |
199 | * Only allow the generic SCSI ioctls if the host can support it. | 239 | * Only allow the generic SCSI ioctls if the host can support it. |
200 | */ | 240 | */ |
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index 64fe0a793efd..75f1cbd61c17 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c | |||
@@ -32,7 +32,7 @@ static bool busy; | |||
32 | static void random_recv_done(struct virtqueue *vq) | 32 | static void random_recv_done(struct virtqueue *vq) |
33 | { | 33 | { |
34 | /* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */ | 34 | /* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */ |
35 | if (!vq->vq_ops->get_buf(vq, &data_avail)) | 35 | if (!virtqueue_get_buf(vq, &data_avail)) |
36 | return; | 36 | return; |
37 | 37 | ||
38 | complete(&have_data); | 38 | complete(&have_data); |
@@ -46,10 +46,10 @@ static void register_buffer(u8 *buf, size_t size) | |||
46 | sg_init_one(&sg, buf, size); | 46 | sg_init_one(&sg, buf, size); |
47 | 47 | ||
48 | /* There should always be room for one buffer. */ | 48 | /* There should always be room for one buffer. */ |
49 | if (vq->vq_ops->add_buf(vq, &sg, 0, 1, buf) < 0) | 49 | if (virtqueue_add_buf(vq, &sg, 0, 1, buf) < 0) |
50 | BUG(); | 50 | BUG(); |
51 | 51 | ||
52 | vq->vq_ops->kick(vq); | 52 | virtqueue_kick(vq); |
53 | } | 53 | } |
54 | 54 | ||
55 | static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait) | 55 | static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait) |
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 196428c2287a..8c99bf1b5e9f 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -33,35 +33,6 @@ | |||
33 | #include <linux/workqueue.h> | 33 | #include <linux/workqueue.h> |
34 | #include "hvc_console.h" | 34 | #include "hvc_console.h" |
35 | 35 | ||
36 | /* Moved here from .h file in order to disable MULTIPORT. */ | ||
37 | #define VIRTIO_CONSOLE_F_MULTIPORT 1 /* Does host provide multiple ports? */ | ||
38 | |||
39 | struct virtio_console_multiport_conf { | ||
40 | struct virtio_console_config config; | ||
41 | /* max. number of ports this device can hold */ | ||
42 | __u32 max_nr_ports; | ||
43 | /* number of ports added so far */ | ||
44 | __u32 nr_ports; | ||
45 | } __attribute__((packed)); | ||
46 | |||
47 | /* | ||
48 | * A message that's passed between the Host and the Guest for a | ||
49 | * particular port. | ||
50 | */ | ||
51 | struct virtio_console_control { | ||
52 | __u32 id; /* Port number */ | ||
53 | __u16 event; /* The kind of control event (see below) */ | ||
54 | __u16 value; /* Extra information for the key */ | ||
55 | }; | ||
56 | |||
57 | /* Some events for control messages */ | ||
58 | #define VIRTIO_CONSOLE_PORT_READY 0 | ||
59 | #define VIRTIO_CONSOLE_CONSOLE_PORT 1 | ||
60 | #define VIRTIO_CONSOLE_RESIZE 2 | ||
61 | #define VIRTIO_CONSOLE_PORT_OPEN 3 | ||
62 | #define VIRTIO_CONSOLE_PORT_NAME 4 | ||
63 | #define VIRTIO_CONSOLE_PORT_REMOVE 5 | ||
64 | |||
65 | /* | 36 | /* |
66 | * This is a global struct for storing common data for all the devices | 37 | * This is a global struct for storing common data for all the devices |
67 | * this driver handles. | 38 | * this driver handles. |
@@ -107,6 +78,9 @@ struct console { | |||
107 | /* The hvc device associated with this console port */ | 78 | /* The hvc device associated with this console port */ |
108 | struct hvc_struct *hvc; | 79 | struct hvc_struct *hvc; |
109 | 80 | ||
81 | /* The size of the console */ | ||
82 | struct winsize ws; | ||
83 | |||
110 | /* | 84 | /* |
111 | * This number identifies the number that we used to register | 85 | * This number identifies the number that we used to register |
112 | * with hvc in hvc_instantiate() and hvc_alloc(); this is the | 86 | * with hvc in hvc_instantiate() and hvc_alloc(); this is the |
@@ -139,7 +113,6 @@ struct ports_device { | |||
139 | * notification | 113 | * notification |
140 | */ | 114 | */ |
141 | struct work_struct control_work; | 115 | struct work_struct control_work; |
142 | struct work_struct config_work; | ||
143 | 116 | ||
144 | struct list_head ports; | 117 | struct list_head ports; |
145 | 118 | ||
@@ -150,7 +123,7 @@ struct ports_device { | |||
150 | spinlock_t cvq_lock; | 123 | spinlock_t cvq_lock; |
151 | 124 | ||
152 | /* The current config space is stored here */ | 125 | /* The current config space is stored here */ |
153 | struct virtio_console_multiport_conf config; | 126 | struct virtio_console_config config; |
154 | 127 | ||
155 | /* The virtio device we're associated with */ | 128 | /* The virtio device we're associated with */ |
156 | struct virtio_device *vdev; | 129 | struct virtio_device *vdev; |
@@ -189,6 +162,9 @@ struct port { | |||
189 | */ | 162 | */ |
190 | spinlock_t inbuf_lock; | 163 | spinlock_t inbuf_lock; |
191 | 164 | ||
165 | /* Protect the operations on the out_vq. */ | ||
166 | spinlock_t outvq_lock; | ||
167 | |||
192 | /* The IO vqs for this port */ | 168 | /* The IO vqs for this port */ |
193 | struct virtqueue *in_vq, *out_vq; | 169 | struct virtqueue *in_vq, *out_vq; |
194 | 170 | ||
@@ -214,6 +190,8 @@ struct port { | |||
214 | /* The 'id' to identify the port with the Host */ | 190 | /* The 'id' to identify the port with the Host */ |
215 | u32 id; | 191 | u32 id; |
216 | 192 | ||
193 | bool outvq_full; | ||
194 | |||
217 | /* Is the host device open */ | 195 | /* Is the host device open */ |
218 | bool host_connected; | 196 | bool host_connected; |
219 | 197 | ||
@@ -328,7 +306,7 @@ static void *get_inbuf(struct port *port) | |||
328 | unsigned int len; | 306 | unsigned int len; |
329 | 307 | ||
330 | vq = port->in_vq; | 308 | vq = port->in_vq; |
331 | buf = vq->vq_ops->get_buf(vq, &len); | 309 | buf = virtqueue_get_buf(vq, &len); |
332 | if (buf) { | 310 | if (buf) { |
333 | buf->len = len; | 311 | buf->len = len; |
334 | buf->offset = 0; | 312 | buf->offset = 0; |
@@ -349,8 +327,8 @@ static int add_inbuf(struct virtqueue *vq, struct port_buffer *buf) | |||
349 | 327 | ||
350 | sg_init_one(sg, buf->buf, buf->size); | 328 | sg_init_one(sg, buf->buf, buf->size); |
351 | 329 | ||
352 | ret = vq->vq_ops->add_buf(vq, sg, 0, 1, buf); | 330 | ret = virtqueue_add_buf(vq, sg, 0, 1, buf); |
353 | vq->vq_ops->kick(vq); | 331 | virtqueue_kick(vq); |
354 | return ret; | 332 | return ret; |
355 | } | 333 | } |
356 | 334 | ||
@@ -366,7 +344,7 @@ static void discard_port_data(struct port *port) | |||
366 | if (port->inbuf) | 344 | if (port->inbuf) |
367 | buf = port->inbuf; | 345 | buf = port->inbuf; |
368 | else | 346 | else |
369 | buf = vq->vq_ops->get_buf(vq, &len); | 347 | buf = virtqueue_get_buf(vq, &len); |
370 | 348 | ||
371 | ret = 0; | 349 | ret = 0; |
372 | while (buf) { | 350 | while (buf) { |
@@ -374,7 +352,7 @@ static void discard_port_data(struct port *port) | |||
374 | ret++; | 352 | ret++; |
375 | free_buf(buf); | 353 | free_buf(buf); |
376 | } | 354 | } |
377 | buf = vq->vq_ops->get_buf(vq, &len); | 355 | buf = virtqueue_get_buf(vq, &len); |
378 | } | 356 | } |
379 | port->inbuf = NULL; | 357 | port->inbuf = NULL; |
380 | if (ret) | 358 | if (ret) |
@@ -403,57 +381,96 @@ out: | |||
403 | return ret; | 381 | return ret; |
404 | } | 382 | } |
405 | 383 | ||
406 | static ssize_t send_control_msg(struct port *port, unsigned int event, | 384 | static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id, |
407 | unsigned int value) | 385 | unsigned int event, unsigned int value) |
408 | { | 386 | { |
409 | struct scatterlist sg[1]; | 387 | struct scatterlist sg[1]; |
410 | struct virtio_console_control cpkt; | 388 | struct virtio_console_control cpkt; |
411 | struct virtqueue *vq; | 389 | struct virtqueue *vq; |
412 | unsigned int len; | 390 | unsigned int len; |
413 | 391 | ||
414 | if (!use_multiport(port->portdev)) | 392 | if (!use_multiport(portdev)) |
415 | return 0; | 393 | return 0; |
416 | 394 | ||
417 | cpkt.id = port->id; | 395 | cpkt.id = port_id; |
418 | cpkt.event = event; | 396 | cpkt.event = event; |
419 | cpkt.value = value; | 397 | cpkt.value = value; |
420 | 398 | ||
421 | vq = port->portdev->c_ovq; | 399 | vq = portdev->c_ovq; |
422 | 400 | ||
423 | sg_init_one(sg, &cpkt, sizeof(cpkt)); | 401 | sg_init_one(sg, &cpkt, sizeof(cpkt)); |
424 | if (vq->vq_ops->add_buf(vq, sg, 1, 0, &cpkt) >= 0) { | 402 | if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt) >= 0) { |
425 | vq->vq_ops->kick(vq); | 403 | virtqueue_kick(vq); |
426 | while (!vq->vq_ops->get_buf(vq, &len)) | 404 | while (!virtqueue_get_buf(vq, &len)) |
427 | cpu_relax(); | 405 | cpu_relax(); |
428 | } | 406 | } |
429 | return 0; | 407 | return 0; |
430 | } | 408 | } |
431 | 409 | ||
432 | static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count) | 410 | static ssize_t send_control_msg(struct port *port, unsigned int event, |
411 | unsigned int value) | ||
412 | { | ||
413 | return __send_control_msg(port->portdev, port->id, event, value); | ||
414 | } | ||
415 | |||
416 | /* Callers must take the port->outvq_lock */ | ||
417 | static void reclaim_consumed_buffers(struct port *port) | ||
418 | { | ||
419 | void *buf; | ||
420 | unsigned int len; | ||
421 | |||
422 | while ((buf = virtqueue_get_buf(port->out_vq, &len))) { | ||
423 | kfree(buf); | ||
424 | port->outvq_full = false; | ||
425 | } | ||
426 | } | ||
427 | |||
428 | static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count, | ||
429 | bool nonblock) | ||
433 | { | 430 | { |
434 | struct scatterlist sg[1]; | 431 | struct scatterlist sg[1]; |
435 | struct virtqueue *out_vq; | 432 | struct virtqueue *out_vq; |
436 | ssize_t ret; | 433 | ssize_t ret; |
434 | unsigned long flags; | ||
437 | unsigned int len; | 435 | unsigned int len; |
438 | 436 | ||
439 | out_vq = port->out_vq; | 437 | out_vq = port->out_vq; |
440 | 438 | ||
439 | spin_lock_irqsave(&port->outvq_lock, flags); | ||
440 | |||
441 | reclaim_consumed_buffers(port); | ||
442 | |||
441 | sg_init_one(sg, in_buf, in_count); | 443 | sg_init_one(sg, in_buf, in_count); |
442 | ret = out_vq->vq_ops->add_buf(out_vq, sg, 1, 0, in_buf); | 444 | ret = virtqueue_add_buf(out_vq, sg, 1, 0, in_buf); |
443 | 445 | ||
444 | /* Tell Host to go! */ | 446 | /* Tell Host to go! */ |
445 | out_vq->vq_ops->kick(out_vq); | 447 | virtqueue_kick(out_vq); |
446 | 448 | ||
447 | if (ret < 0) { | 449 | if (ret < 0) { |
448 | in_count = 0; | 450 | in_count = 0; |
449 | goto fail; | 451 | goto done; |
450 | } | 452 | } |
451 | 453 | ||
452 | /* Wait till the host acknowledges it pushed out the data we sent. */ | 454 | if (ret == 0) |
453 | while (!out_vq->vq_ops->get_buf(out_vq, &len)) | 455 | port->outvq_full = true; |
456 | |||
457 | if (nonblock) | ||
458 | goto done; | ||
459 | |||
460 | /* | ||
461 | * Wait till the host acknowledges it pushed out the data we | ||
462 | * sent. This is done for ports in blocking mode or for data | ||
463 | * from the hvc_console; the tty operations are performed with | ||
464 | * spinlocks held so we can't sleep here. | ||
465 | */ | ||
466 | while (!virtqueue_get_buf(out_vq, &len)) | ||
454 | cpu_relax(); | 467 | cpu_relax(); |
455 | fail: | 468 | done: |
456 | /* We're expected to return the amount of data we wrote */ | 469 | spin_unlock_irqrestore(&port->outvq_lock, flags); |
470 | /* | ||
471 | * We're expected to return the amount of data we wrote -- all | ||
472 | * of it | ||
473 | */ | ||
457 | return in_count; | 474 | return in_count; |
458 | } | 475 | } |
459 | 476 | ||
@@ -503,9 +520,28 @@ static ssize_t fill_readbuf(struct port *port, char *out_buf, size_t out_count, | |||
503 | } | 520 | } |
504 | 521 | ||
505 | /* The condition that must be true for polling to end */ | 522 | /* The condition that must be true for polling to end */ |
506 | static bool wait_is_over(struct port *port) | 523 | static bool will_read_block(struct port *port) |
524 | { | ||
525 | return !port_has_data(port) && port->host_connected; | ||
526 | } | ||
527 | |||
528 | static bool will_write_block(struct port *port) | ||
507 | { | 529 | { |
508 | return port_has_data(port) || !port->host_connected; | 530 | bool ret; |
531 | |||
532 | if (!port->host_connected) | ||
533 | return true; | ||
534 | |||
535 | spin_lock_irq(&port->outvq_lock); | ||
536 | /* | ||
537 | * Check if the Host has consumed any buffers since we last | ||
538 | * sent data (this is only applicable for nonblocking ports). | ||
539 | */ | ||
540 | reclaim_consumed_buffers(port); | ||
541 | ret = port->outvq_full; | ||
542 | spin_unlock_irq(&port->outvq_lock); | ||
543 | |||
544 | return ret; | ||
509 | } | 545 | } |
510 | 546 | ||
511 | static ssize_t port_fops_read(struct file *filp, char __user *ubuf, | 547 | static ssize_t port_fops_read(struct file *filp, char __user *ubuf, |
@@ -528,7 +564,7 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf, | |||
528 | return -EAGAIN; | 564 | return -EAGAIN; |
529 | 565 | ||
530 | ret = wait_event_interruptible(port->waitqueue, | 566 | ret = wait_event_interruptible(port->waitqueue, |
531 | wait_is_over(port)); | 567 | !will_read_block(port)); |
532 | if (ret < 0) | 568 | if (ret < 0) |
533 | return ret; | 569 | return ret; |
534 | } | 570 | } |
@@ -554,9 +590,22 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, | |||
554 | struct port *port; | 590 | struct port *port; |
555 | char *buf; | 591 | char *buf; |
556 | ssize_t ret; | 592 | ssize_t ret; |
593 | bool nonblock; | ||
557 | 594 | ||
558 | port = filp->private_data; | 595 | port = filp->private_data; |
559 | 596 | ||
597 | nonblock = filp->f_flags & O_NONBLOCK; | ||
598 | |||
599 | if (will_write_block(port)) { | ||
600 | if (nonblock) | ||
601 | return -EAGAIN; | ||
602 | |||
603 | ret = wait_event_interruptible(port->waitqueue, | ||
604 | !will_write_block(port)); | ||
605 | if (ret < 0) | ||
606 | return ret; | ||
607 | } | ||
608 | |||
560 | count = min((size_t)(32 * 1024), count); | 609 | count = min((size_t)(32 * 1024), count); |
561 | 610 | ||
562 | buf = kmalloc(count, GFP_KERNEL); | 611 | buf = kmalloc(count, GFP_KERNEL); |
@@ -569,9 +618,14 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, | |||
569 | goto free_buf; | 618 | goto free_buf; |
570 | } | 619 | } |
571 | 620 | ||
572 | ret = send_buf(port, buf, count); | 621 | ret = send_buf(port, buf, count, nonblock); |
622 | |||
623 | if (nonblock && ret > 0) | ||
624 | goto out; | ||
625 | |||
573 | free_buf: | 626 | free_buf: |
574 | kfree(buf); | 627 | kfree(buf); |
628 | out: | ||
575 | return ret; | 629 | return ret; |
576 | } | 630 | } |
577 | 631 | ||
@@ -586,7 +640,7 @@ static unsigned int port_fops_poll(struct file *filp, poll_table *wait) | |||
586 | ret = 0; | 640 | ret = 0; |
587 | if (port->inbuf) | 641 | if (port->inbuf) |
588 | ret |= POLLIN | POLLRDNORM; | 642 | ret |= POLLIN | POLLRDNORM; |
589 | if (port->host_connected) | 643 | if (!will_write_block(port)) |
590 | ret |= POLLOUT; | 644 | ret |= POLLOUT; |
591 | if (!port->host_connected) | 645 | if (!port->host_connected) |
592 | ret |= POLLHUP; | 646 | ret |= POLLHUP; |
@@ -610,6 +664,10 @@ static int port_fops_release(struct inode *inode, struct file *filp) | |||
610 | 664 | ||
611 | spin_unlock_irq(&port->inbuf_lock); | 665 | spin_unlock_irq(&port->inbuf_lock); |
612 | 666 | ||
667 | spin_lock_irq(&port->outvq_lock); | ||
668 | reclaim_consumed_buffers(port); | ||
669 | spin_unlock_irq(&port->outvq_lock); | ||
670 | |||
613 | return 0; | 671 | return 0; |
614 | } | 672 | } |
615 | 673 | ||
@@ -638,6 +696,15 @@ static int port_fops_open(struct inode *inode, struct file *filp) | |||
638 | port->guest_connected = true; | 696 | port->guest_connected = true; |
639 | spin_unlock_irq(&port->inbuf_lock); | 697 | spin_unlock_irq(&port->inbuf_lock); |
640 | 698 | ||
699 | spin_lock_irq(&port->outvq_lock); | ||
700 | /* | ||
701 | * There might be a chance that we missed reclaiming a few | ||
702 | * buffers in the window of the port getting previously closed | ||
703 | * and opening now. | ||
704 | */ | ||
705 | reclaim_consumed_buffers(port); | ||
706 | spin_unlock_irq(&port->outvq_lock); | ||
707 | |||
641 | /* Notify host of port being opened */ | 708 | /* Notify host of port being opened */ |
642 | send_control_msg(filp->private_data, VIRTIO_CONSOLE_PORT_OPEN, 1); | 709 | send_control_msg(filp->private_data, VIRTIO_CONSOLE_PORT_OPEN, 1); |
643 | 710 | ||
@@ -676,9 +743,9 @@ static int put_chars(u32 vtermno, const char *buf, int count) | |||
676 | 743 | ||
677 | port = find_port_by_vtermno(vtermno); | 744 | port = find_port_by_vtermno(vtermno); |
678 | if (!port) | 745 | if (!port) |
679 | return 0; | 746 | return -EPIPE; |
680 | 747 | ||
681 | return send_buf(port, (void *)buf, count); | 748 | return send_buf(port, (void *)buf, count, false); |
682 | } | 749 | } |
683 | 750 | ||
684 | /* | 751 | /* |
@@ -692,9 +759,13 @@ static int get_chars(u32 vtermno, char *buf, int count) | |||
692 | { | 759 | { |
693 | struct port *port; | 760 | struct port *port; |
694 | 761 | ||
762 | /* If we've not set up the port yet, we have no input to give. */ | ||
763 | if (unlikely(early_put_chars)) | ||
764 | return 0; | ||
765 | |||
695 | port = find_port_by_vtermno(vtermno); | 766 | port = find_port_by_vtermno(vtermno); |
696 | if (!port) | 767 | if (!port) |
697 | return 0; | 768 | return -EPIPE; |
698 | 769 | ||
699 | /* If we don't have an input queue yet, we can't get input. */ | 770 | /* If we don't have an input queue yet, we can't get input. */ |
700 | BUG_ON(!port->in_vq); | 771 | BUG_ON(!port->in_vq); |
@@ -705,22 +776,14 @@ static int get_chars(u32 vtermno, char *buf, int count) | |||
705 | static void resize_console(struct port *port) | 776 | static void resize_console(struct port *port) |
706 | { | 777 | { |
707 | struct virtio_device *vdev; | 778 | struct virtio_device *vdev; |
708 | struct winsize ws; | ||
709 | 779 | ||
710 | /* The port could have been hot-unplugged */ | 780 | /* The port could have been hot-unplugged */ |
711 | if (!port) | 781 | if (!port || !is_console_port(port)) |
712 | return; | 782 | return; |
713 | 783 | ||
714 | vdev = port->portdev->vdev; | 784 | vdev = port->portdev->vdev; |
715 | if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_SIZE)) { | 785 | if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_SIZE)) |
716 | vdev->config->get(vdev, | 786 | hvc_resize(port->cons.hvc, port->cons.ws); |
717 | offsetof(struct virtio_console_config, cols), | ||
718 | &ws.ws_col, sizeof(u16)); | ||
719 | vdev->config->get(vdev, | ||
720 | offsetof(struct virtio_console_config, rows), | ||
721 | &ws.ws_row, sizeof(u16)); | ||
722 | hvc_resize(port->cons.hvc, ws); | ||
723 | } | ||
724 | } | 787 | } |
725 | 788 | ||
726 | /* We set the configuration at this point, since we now have a tty */ | 789 | /* We set the configuration at this point, since we now have a tty */ |
@@ -804,6 +867,13 @@ int init_port_console(struct port *port) | |||
804 | spin_unlock_irq(&pdrvdata_lock); | 867 | spin_unlock_irq(&pdrvdata_lock); |
805 | port->guest_connected = true; | 868 | port->guest_connected = true; |
806 | 869 | ||
870 | /* | ||
871 | * Start using the new console output if this is the first | ||
872 | * console to come up. | ||
873 | */ | ||
874 | if (early_put_chars) | ||
875 | early_put_chars = NULL; | ||
876 | |||
807 | /* Notify host of port being opened */ | 877 | /* Notify host of port being opened */ |
808 | send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 1); | 878 | send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 1); |
809 | 879 | ||
@@ -859,6 +929,8 @@ static ssize_t debugfs_read(struct file *filp, char __user *ubuf, | |||
859 | out_offset += snprintf(buf + out_offset, out_count - out_offset, | 929 | out_offset += snprintf(buf + out_offset, out_count - out_offset, |
860 | "host_connected: %d\n", port->host_connected); | 930 | "host_connected: %d\n", port->host_connected); |
861 | out_offset += snprintf(buf + out_offset, out_count - out_offset, | 931 | out_offset += snprintf(buf + out_offset, out_count - out_offset, |
932 | "outvq_full: %d\n", port->outvq_full); | ||
933 | out_offset += snprintf(buf + out_offset, out_count - out_offset, | ||
862 | "is_console: %s\n", | 934 | "is_console: %s\n", |
863 | is_console_port(port) ? "yes" : "no"); | 935 | is_console_port(port) ? "yes" : "no"); |
864 | out_offset += snprintf(buf + out_offset, out_count - out_offset, | 936 | out_offset += snprintf(buf + out_offset, out_count - out_offset, |
@@ -875,6 +947,153 @@ static const struct file_operations port_debugfs_ops = { | |||
875 | .read = debugfs_read, | 947 | .read = debugfs_read, |
876 | }; | 948 | }; |
877 | 949 | ||
950 | static void set_console_size(struct port *port, u16 rows, u16 cols) | ||
951 | { | ||
952 | if (!port || !is_console_port(port)) | ||
953 | return; | ||
954 | |||
955 | port->cons.ws.ws_row = rows; | ||
956 | port->cons.ws.ws_col = cols; | ||
957 | } | ||
958 | |||
959 | static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock) | ||
960 | { | ||
961 | struct port_buffer *buf; | ||
962 | unsigned int nr_added_bufs; | ||
963 | int ret; | ||
964 | |||
965 | nr_added_bufs = 0; | ||
966 | do { | ||
967 | buf = alloc_buf(PAGE_SIZE); | ||
968 | if (!buf) | ||
969 | break; | ||
970 | |||
971 | spin_lock_irq(lock); | ||
972 | ret = add_inbuf(vq, buf); | ||
973 | if (ret < 0) { | ||
974 | spin_unlock_irq(lock); | ||
975 | free_buf(buf); | ||
976 | break; | ||
977 | } | ||
978 | nr_added_bufs++; | ||
979 | spin_unlock_irq(lock); | ||
980 | } while (ret > 0); | ||
981 | |||
982 | return nr_added_bufs; | ||
983 | } | ||
984 | |||
985 | static int add_port(struct ports_device *portdev, u32 id) | ||
986 | { | ||
987 | char debugfs_name[16]; | ||
988 | struct port *port; | ||
989 | struct port_buffer *buf; | ||
990 | dev_t devt; | ||
991 | unsigned int nr_added_bufs; | ||
992 | int err; | ||
993 | |||
994 | port = kmalloc(sizeof(*port), GFP_KERNEL); | ||
995 | if (!port) { | ||
996 | err = -ENOMEM; | ||
997 | goto fail; | ||
998 | } | ||
999 | |||
1000 | port->portdev = portdev; | ||
1001 | port->id = id; | ||
1002 | |||
1003 | port->name = NULL; | ||
1004 | port->inbuf = NULL; | ||
1005 | port->cons.hvc = NULL; | ||
1006 | |||
1007 | port->cons.ws.ws_row = port->cons.ws.ws_col = 0; | ||
1008 | |||
1009 | port->host_connected = port->guest_connected = false; | ||
1010 | |||
1011 | port->outvq_full = false; | ||
1012 | |||
1013 | port->in_vq = portdev->in_vqs[port->id]; | ||
1014 | port->out_vq = portdev->out_vqs[port->id]; | ||
1015 | |||
1016 | cdev_init(&port->cdev, &port_fops); | ||
1017 | |||
1018 | devt = MKDEV(portdev->chr_major, id); | ||
1019 | err = cdev_add(&port->cdev, devt, 1); | ||
1020 | if (err < 0) { | ||
1021 | dev_err(&port->portdev->vdev->dev, | ||
1022 | "Error %d adding cdev for port %u\n", err, id); | ||
1023 | goto free_port; | ||
1024 | } | ||
1025 | port->dev = device_create(pdrvdata.class, &port->portdev->vdev->dev, | ||
1026 | devt, port, "vport%up%u", | ||
1027 | port->portdev->drv_index, id); | ||
1028 | if (IS_ERR(port->dev)) { | ||
1029 | err = PTR_ERR(port->dev); | ||
1030 | dev_err(&port->portdev->vdev->dev, | ||
1031 | "Error %d creating device for port %u\n", | ||
1032 | err, id); | ||
1033 | goto free_cdev; | ||
1034 | } | ||
1035 | |||
1036 | spin_lock_init(&port->inbuf_lock); | ||
1037 | spin_lock_init(&port->outvq_lock); | ||
1038 | init_waitqueue_head(&port->waitqueue); | ||
1039 | |||
1040 | /* Fill the in_vq with buffers so the host can send us data. */ | ||
1041 | nr_added_bufs = fill_queue(port->in_vq, &port->inbuf_lock); | ||
1042 | if (!nr_added_bufs) { | ||
1043 | dev_err(port->dev, "Error allocating inbufs\n"); | ||
1044 | err = -ENOMEM; | ||
1045 | goto free_device; | ||
1046 | } | ||
1047 | |||
1048 | /* | ||
1049 | * If we're not using multiport support, this has to be a console port | ||
1050 | */ | ||
1051 | if (!use_multiport(port->portdev)) { | ||
1052 | err = init_port_console(port); | ||
1053 | if (err) | ||
1054 | goto free_inbufs; | ||
1055 | } | ||
1056 | |||
1057 | spin_lock_irq(&portdev->ports_lock); | ||
1058 | list_add_tail(&port->list, &port->portdev->ports); | ||
1059 | spin_unlock_irq(&portdev->ports_lock); | ||
1060 | |||
1061 | /* | ||
1062 | * Tell the Host we're set so that it can send us various | ||
1063 | * configuration parameters for this port (eg, port name, | ||
1064 | * caching, whether this is a console port, etc.) | ||
1065 | */ | ||
1066 | send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1); | ||
1067 | |||
1068 | if (pdrvdata.debugfs_dir) { | ||
1069 | /* | ||
1070 | * Finally, create the debugfs file that we can use to | ||
1071 | * inspect a port's state at any time | ||
1072 | */ | ||
1073 | sprintf(debugfs_name, "vport%up%u", | ||
1074 | port->portdev->drv_index, id); | ||
1075 | port->debugfs_file = debugfs_create_file(debugfs_name, 0444, | ||
1076 | pdrvdata.debugfs_dir, | ||
1077 | port, | ||
1078 | &port_debugfs_ops); | ||
1079 | } | ||
1080 | return 0; | ||
1081 | |||
1082 | free_inbufs: | ||
1083 | while ((buf = virtqueue_detach_unused_buf(port->in_vq))) | ||
1084 | free_buf(buf); | ||
1085 | free_device: | ||
1086 | device_destroy(pdrvdata.class, port->dev->devt); | ||
1087 | free_cdev: | ||
1088 | cdev_del(&port->cdev); | ||
1089 | free_port: | ||
1090 | kfree(port); | ||
1091 | fail: | ||
1092 | /* The host might want to notify management sw about port add failure */ | ||
1093 | __send_control_msg(portdev, id, VIRTIO_CONSOLE_PORT_READY, 0); | ||
1094 | return err; | ||
1095 | } | ||
1096 | |||
878 | /* Remove all port-specific data. */ | 1097 | /* Remove all port-specific data. */ |
879 | static int remove_port(struct port *port) | 1098 | static int remove_port(struct port *port) |
880 | { | 1099 | { |
@@ -888,7 +1107,18 @@ static int remove_port(struct port *port) | |||
888 | spin_lock_irq(&pdrvdata_lock); | 1107 | spin_lock_irq(&pdrvdata_lock); |
889 | list_del(&port->cons.list); | 1108 | list_del(&port->cons.list); |
890 | spin_unlock_irq(&pdrvdata_lock); | 1109 | spin_unlock_irq(&pdrvdata_lock); |
1110 | #if 0 | ||
1111 | /* | ||
1112 | * hvc_remove() not called as removing one hvc port | ||
1113 | * results in other hvc ports getting frozen. | ||
1114 | * | ||
1115 | * Once this is resolved in hvc, this functionality | ||
1116 | * will be enabled. Till that is done, the -EPIPE | ||
1117 | * return from get_chars() above will help | ||
1118 | * hvc_console.c to clean up on ports we remove here. | ||
1119 | */ | ||
891 | hvc_remove(port->cons.hvc); | 1120 | hvc_remove(port->cons.hvc); |
1121 | #endif | ||
892 | } | 1122 | } |
893 | if (port->guest_connected) | 1123 | if (port->guest_connected) |
894 | send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0); | 1124 | send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0); |
@@ -900,8 +1130,10 @@ static int remove_port(struct port *port) | |||
900 | /* Remove unused data this port might have received. */ | 1130 | /* Remove unused data this port might have received. */ |
901 | discard_port_data(port); | 1131 | discard_port_data(port); |
902 | 1132 | ||
1133 | reclaim_consumed_buffers(port); | ||
1134 | |||
903 | /* Remove buffers we queued up for the Host to send us data in. */ | 1135 | /* Remove buffers we queued up for the Host to send us data in. */ |
904 | while ((buf = port->in_vq->vq_ops->detach_unused_buf(port->in_vq))) | 1136 | while ((buf = virtqueue_detach_unused_buf(port->in_vq))) |
905 | free_buf(buf); | 1137 | free_buf(buf); |
906 | 1138 | ||
907 | kfree(port->name); | 1139 | kfree(port->name); |
@@ -924,7 +1156,7 @@ static void handle_control_message(struct ports_device *portdev, | |||
924 | cpkt = (struct virtio_console_control *)(buf->buf + buf->offset); | 1156 | cpkt = (struct virtio_console_control *)(buf->buf + buf->offset); |
925 | 1157 | ||
926 | port = find_port_by_id(portdev, cpkt->id); | 1158 | port = find_port_by_id(portdev, cpkt->id); |
927 | if (!port) { | 1159 | if (!port && cpkt->event != VIRTIO_CONSOLE_PORT_ADD) { |
928 | /* No valid header at start of buffer. Drop it. */ | 1160 | /* No valid header at start of buffer. Drop it. */ |
929 | dev_dbg(&portdev->vdev->dev, | 1161 | dev_dbg(&portdev->vdev->dev, |
930 | "Invalid index %u in control packet\n", cpkt->id); | 1162 | "Invalid index %u in control packet\n", cpkt->id); |
@@ -932,6 +1164,24 @@ static void handle_control_message(struct ports_device *portdev, | |||
932 | } | 1164 | } |
933 | 1165 | ||
934 | switch (cpkt->event) { | 1166 | switch (cpkt->event) { |
1167 | case VIRTIO_CONSOLE_PORT_ADD: | ||
1168 | if (port) { | ||
1169 | dev_dbg(&portdev->vdev->dev, | ||
1170 | "Port %u already added\n", port->id); | ||
1171 | send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1); | ||
1172 | break; | ||
1173 | } | ||
1174 | if (cpkt->id >= portdev->config.max_nr_ports) { | ||
1175 | dev_warn(&portdev->vdev->dev, | ||
1176 | "Request for adding port with out-of-bound id %u, max. supported id: %u\n", | ||
1177 | cpkt->id, portdev->config.max_nr_ports - 1); | ||
1178 | break; | ||
1179 | } | ||
1180 | add_port(portdev, cpkt->id); | ||
1181 | break; | ||
1182 | case VIRTIO_CONSOLE_PORT_REMOVE: | ||
1183 | remove_port(port); | ||
1184 | break; | ||
935 | case VIRTIO_CONSOLE_CONSOLE_PORT: | 1185 | case VIRTIO_CONSOLE_CONSOLE_PORT: |
936 | if (!cpkt->value) | 1186 | if (!cpkt->value) |
937 | break; | 1187 | break; |
@@ -944,15 +1194,34 @@ static void handle_control_message(struct ports_device *portdev, | |||
944 | * have to notify the host first. | 1194 | * have to notify the host first. |
945 | */ | 1195 | */ |
946 | break; | 1196 | break; |
947 | case VIRTIO_CONSOLE_RESIZE: | 1197 | case VIRTIO_CONSOLE_RESIZE: { |
1198 | struct { | ||
1199 | __u16 rows; | ||
1200 | __u16 cols; | ||
1201 | } size; | ||
1202 | |||
948 | if (!is_console_port(port)) | 1203 | if (!is_console_port(port)) |
949 | break; | 1204 | break; |
1205 | |||
1206 | memcpy(&size, buf->buf + buf->offset + sizeof(*cpkt), | ||
1207 | sizeof(size)); | ||
1208 | set_console_size(port, size.rows, size.cols); | ||
1209 | |||
950 | port->cons.hvc->irq_requested = 1; | 1210 | port->cons.hvc->irq_requested = 1; |
951 | resize_console(port); | 1211 | resize_console(port); |
952 | break; | 1212 | break; |
1213 | } | ||
953 | case VIRTIO_CONSOLE_PORT_OPEN: | 1214 | case VIRTIO_CONSOLE_PORT_OPEN: |
954 | port->host_connected = cpkt->value; | 1215 | port->host_connected = cpkt->value; |
955 | wake_up_interruptible(&port->waitqueue); | 1216 | wake_up_interruptible(&port->waitqueue); |
1217 | /* | ||
1218 | * If the host port got closed and the host had any | ||
1219 | * unconsumed buffers, we'll be able to reclaim them | ||
1220 | * now. | ||
1221 | */ | ||
1222 | spin_lock_irq(&port->outvq_lock); | ||
1223 | reclaim_consumed_buffers(port); | ||
1224 | spin_unlock_irq(&port->outvq_lock); | ||
956 | break; | 1225 | break; |
957 | case VIRTIO_CONSOLE_PORT_NAME: | 1226 | case VIRTIO_CONSOLE_PORT_NAME: |
958 | /* | 1227 | /* |
@@ -990,32 +1259,6 @@ static void handle_control_message(struct ports_device *portdev, | |||
990 | kobject_uevent(&port->dev->kobj, KOBJ_CHANGE); | 1259 | kobject_uevent(&port->dev->kobj, KOBJ_CHANGE); |
991 | } | 1260 | } |
992 | break; | 1261 | break; |
993 | case VIRTIO_CONSOLE_PORT_REMOVE: | ||
994 | /* | ||
995 | * Hot unplug the port. We don't decrement nr_ports | ||
996 | * since we don't want to deal with extra complexities | ||
997 | * of using the lowest-available port id: We can just | ||
998 | * pick up the nr_ports number as the id and not have | ||
999 | * userspace send it to us. This helps us in two | ||
1000 | * ways: | ||
1001 | * | ||
1002 | * - We don't need to have a 'port_id' field in the | ||
1003 | * config space when a port is hot-added. This is a | ||
1004 | * good thing as we might queue up multiple hotplug | ||
1005 | * requests issued in our workqueue. | ||
1006 | * | ||
1007 | * - Another way to deal with this would have been to | ||
1008 | * use a bitmap of the active ports and select the | ||
1009 | * lowest non-active port from that map. That | ||
1010 | * bloats the already tight config space and we | ||
1011 | * would end up artificially limiting the | ||
1012 | * max. number of ports to sizeof(bitmap). Right | ||
1013 | * now we can support 2^32 ports (as the port id is | ||
1014 | * stored in a u32 type). | ||
1015 | * | ||
1016 | */ | ||
1017 | remove_port(port); | ||
1018 | break; | ||
1019 | } | 1262 | } |
1020 | } | 1263 | } |
1021 | 1264 | ||
@@ -1030,7 +1273,7 @@ static void control_work_handler(struct work_struct *work) | |||
1030 | vq = portdev->c_ivq; | 1273 | vq = portdev->c_ivq; |
1031 | 1274 | ||
1032 | spin_lock(&portdev->cvq_lock); | 1275 | spin_lock(&portdev->cvq_lock); |
1033 | while ((buf = vq->vq_ops->get_buf(vq, &len))) { | 1276 | while ((buf = virtqueue_get_buf(vq, &len))) { |
1034 | spin_unlock(&portdev->cvq_lock); | 1277 | spin_unlock(&portdev->cvq_lock); |
1035 | 1278 | ||
1036 | buf->len = len; | 1279 | buf->len = len; |
@@ -1092,204 +1335,29 @@ static void config_intr(struct virtio_device *vdev) | |||
1092 | struct ports_device *portdev; | 1335 | struct ports_device *portdev; |
1093 | 1336 | ||
1094 | portdev = vdev->priv; | 1337 | portdev = vdev->priv; |
1095 | if (use_multiport(portdev)) { | ||
1096 | /* Handle port hot-add */ | ||
1097 | schedule_work(&portdev->config_work); | ||
1098 | } | ||
1099 | /* | ||
1100 | * We'll use this way of resizing only for legacy support. | ||
1101 | * For newer userspace (VIRTIO_CONSOLE_F_MULTPORT+), use | ||
1102 | * control messages to indicate console size changes so that | ||
1103 | * it can be done per-port | ||
1104 | */ | ||
1105 | resize_console(find_port_by_id(portdev, 0)); | ||
1106 | } | ||
1107 | |||
1108 | static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock) | ||
1109 | { | ||
1110 | struct port_buffer *buf; | ||
1111 | unsigned int nr_added_bufs; | ||
1112 | int ret; | ||
1113 | |||
1114 | nr_added_bufs = 0; | ||
1115 | do { | ||
1116 | buf = alloc_buf(PAGE_SIZE); | ||
1117 | if (!buf) | ||
1118 | break; | ||
1119 | |||
1120 | spin_lock_irq(lock); | ||
1121 | ret = add_inbuf(vq, buf); | ||
1122 | if (ret < 0) { | ||
1123 | spin_unlock_irq(lock); | ||
1124 | free_buf(buf); | ||
1125 | break; | ||
1126 | } | ||
1127 | nr_added_bufs++; | ||
1128 | spin_unlock_irq(lock); | ||
1129 | } while (ret > 0); | ||
1130 | |||
1131 | return nr_added_bufs; | ||
1132 | } | ||
1133 | |||
1134 | static int add_port(struct ports_device *portdev, u32 id) | ||
1135 | { | ||
1136 | char debugfs_name[16]; | ||
1137 | struct port *port; | ||
1138 | struct port_buffer *buf; | ||
1139 | dev_t devt; | ||
1140 | unsigned int nr_added_bufs; | ||
1141 | int err; | ||
1142 | |||
1143 | port = kmalloc(sizeof(*port), GFP_KERNEL); | ||
1144 | if (!port) { | ||
1145 | err = -ENOMEM; | ||
1146 | goto fail; | ||
1147 | } | ||
1148 | |||
1149 | port->portdev = portdev; | ||
1150 | port->id = id; | ||
1151 | |||
1152 | port->name = NULL; | ||
1153 | port->inbuf = NULL; | ||
1154 | port->cons.hvc = NULL; | ||
1155 | |||
1156 | port->host_connected = port->guest_connected = false; | ||
1157 | |||
1158 | port->in_vq = portdev->in_vqs[port->id]; | ||
1159 | port->out_vq = portdev->out_vqs[port->id]; | ||
1160 | |||
1161 | cdev_init(&port->cdev, &port_fops); | ||
1162 | |||
1163 | devt = MKDEV(portdev->chr_major, id); | ||
1164 | err = cdev_add(&port->cdev, devt, 1); | ||
1165 | if (err < 0) { | ||
1166 | dev_err(&port->portdev->vdev->dev, | ||
1167 | "Error %d adding cdev for port %u\n", err, id); | ||
1168 | goto free_port; | ||
1169 | } | ||
1170 | port->dev = device_create(pdrvdata.class, &port->portdev->vdev->dev, | ||
1171 | devt, port, "vport%up%u", | ||
1172 | port->portdev->drv_index, id); | ||
1173 | if (IS_ERR(port->dev)) { | ||
1174 | err = PTR_ERR(port->dev); | ||
1175 | dev_err(&port->portdev->vdev->dev, | ||
1176 | "Error %d creating device for port %u\n", | ||
1177 | err, id); | ||
1178 | goto free_cdev; | ||
1179 | } | ||
1180 | |||
1181 | spin_lock_init(&port->inbuf_lock); | ||
1182 | init_waitqueue_head(&port->waitqueue); | ||
1183 | |||
1184 | /* Fill the in_vq with buffers so the host can send us data. */ | ||
1185 | nr_added_bufs = fill_queue(port->in_vq, &port->inbuf_lock); | ||
1186 | if (!nr_added_bufs) { | ||
1187 | dev_err(port->dev, "Error allocating inbufs\n"); | ||
1188 | err = -ENOMEM; | ||
1189 | goto free_device; | ||
1190 | } | ||
1191 | |||
1192 | /* | ||
1193 | * If we're not using multiport support, this has to be a console port | ||
1194 | */ | ||
1195 | if (!use_multiport(port->portdev)) { | ||
1196 | err = init_port_console(port); | ||
1197 | if (err) | ||
1198 | goto free_inbufs; | ||
1199 | } | ||
1200 | |||
1201 | spin_lock_irq(&portdev->ports_lock); | ||
1202 | list_add_tail(&port->list, &port->portdev->ports); | ||
1203 | spin_unlock_irq(&portdev->ports_lock); | ||
1204 | |||
1205 | /* | ||
1206 | * Tell the Host we're set so that it can send us various | ||
1207 | * configuration parameters for this port (eg, port name, | ||
1208 | * caching, whether this is a console port, etc.) | ||
1209 | */ | ||
1210 | send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1); | ||
1211 | |||
1212 | if (pdrvdata.debugfs_dir) { | ||
1213 | /* | ||
1214 | * Finally, create the debugfs file that we can use to | ||
1215 | * inspect a port's state at any time | ||
1216 | */ | ||
1217 | sprintf(debugfs_name, "vport%up%u", | ||
1218 | port->portdev->drv_index, id); | ||
1219 | port->debugfs_file = debugfs_create_file(debugfs_name, 0444, | ||
1220 | pdrvdata.debugfs_dir, | ||
1221 | port, | ||
1222 | &port_debugfs_ops); | ||
1223 | } | ||
1224 | return 0; | ||
1225 | |||
1226 | free_inbufs: | ||
1227 | while ((buf = port->in_vq->vq_ops->detach_unused_buf(port->in_vq))) | ||
1228 | free_buf(buf); | ||
1229 | free_device: | ||
1230 | device_destroy(pdrvdata.class, port->dev->devt); | ||
1231 | free_cdev: | ||
1232 | cdev_del(&port->cdev); | ||
1233 | free_port: | ||
1234 | kfree(port); | ||
1235 | fail: | ||
1236 | return err; | ||
1237 | } | ||
1238 | 1338 | ||
1239 | /* | 1339 | if (!use_multiport(portdev)) { |
1240 | * The workhandler for config-space updates. | 1340 | struct port *port; |
1241 | * | 1341 | u16 rows, cols; |
1242 | * This is called when ports are hot-added. | ||
1243 | */ | ||
1244 | static void config_work_handler(struct work_struct *work) | ||
1245 | { | ||
1246 | struct virtio_console_multiport_conf virtconconf; | ||
1247 | struct ports_device *portdev; | ||
1248 | struct virtio_device *vdev; | ||
1249 | int err; | ||
1250 | 1342 | ||
1251 | portdev = container_of(work, struct ports_device, config_work); | 1343 | vdev->config->get(vdev, |
1344 | offsetof(struct virtio_console_config, cols), | ||
1345 | &cols, sizeof(u16)); | ||
1346 | vdev->config->get(vdev, | ||
1347 | offsetof(struct virtio_console_config, rows), | ||
1348 | &rows, sizeof(u16)); | ||
1252 | 1349 | ||
1253 | vdev = portdev->vdev; | 1350 | port = find_port_by_id(portdev, 0); |
1254 | vdev->config->get(vdev, | 1351 | set_console_size(port, rows, cols); |
1255 | offsetof(struct virtio_console_multiport_conf, | ||
1256 | nr_ports), | ||
1257 | &virtconconf.nr_ports, | ||
1258 | sizeof(virtconconf.nr_ports)); | ||
1259 | 1352 | ||
1260 | if (portdev->config.nr_ports == virtconconf.nr_ports) { | ||
1261 | /* | 1353 | /* |
1262 | * Port 0 got hot-added. Since we already did all the | 1354 | * We'll use this way of resizing only for legacy |
1263 | * other initialisation for it, just tell the Host | 1355 | * support. For newer userspace |
1264 | * that the port is ready if we find the port. In | 1356 | * (VIRTIO_CONSOLE_F_MULTPORT+), use control messages |
1265 | * case the port was hot-removed earlier, we call | 1357 | * to indicate console size changes so that it can be |
1266 | * add_port to add the port. | 1358 | * done per-port. |
1267 | */ | 1359 | */ |
1268 | struct port *port; | 1360 | resize_console(port); |
1269 | |||
1270 | port = find_port_by_id(portdev, 0); | ||
1271 | if (!port) | ||
1272 | add_port(portdev, 0); | ||
1273 | else | ||
1274 | send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1); | ||
1275 | return; | ||
1276 | } | ||
1277 | if (virtconconf.nr_ports > portdev->config.max_nr_ports) { | ||
1278 | dev_warn(&vdev->dev, | ||
1279 | "More ports specified (%u) than allowed (%u)", | ||
1280 | portdev->config.nr_ports + 1, | ||
1281 | portdev->config.max_nr_ports); | ||
1282 | return; | ||
1283 | } | ||
1284 | if (virtconconf.nr_ports < portdev->config.nr_ports) | ||
1285 | return; | ||
1286 | |||
1287 | /* Hot-add ports */ | ||
1288 | while (virtconconf.nr_ports - portdev->config.nr_ports) { | ||
1289 | err = add_port(portdev, portdev->config.nr_ports); | ||
1290 | if (err) | ||
1291 | break; | ||
1292 | portdev->config.nr_ports++; | ||
1293 | } | 1361 | } |
1294 | } | 1362 | } |
1295 | 1363 | ||
@@ -1414,7 +1482,6 @@ static const struct file_operations portdev_fops = { | |||
1414 | static int __devinit virtcons_probe(struct virtio_device *vdev) | 1482 | static int __devinit virtcons_probe(struct virtio_device *vdev) |
1415 | { | 1483 | { |
1416 | struct ports_device *portdev; | 1484 | struct ports_device *portdev; |
1417 | u32 i; | ||
1418 | int err; | 1485 | int err; |
1419 | bool multiport; | 1486 | bool multiport; |
1420 | 1487 | ||
@@ -1443,37 +1510,19 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) | |||
1443 | } | 1510 | } |
1444 | 1511 | ||
1445 | multiport = false; | 1512 | multiport = false; |
1446 | portdev->config.nr_ports = 1; | ||
1447 | portdev->config.max_nr_ports = 1; | 1513 | portdev->config.max_nr_ports = 1; |
1448 | #if 0 /* Multiport is not quite ready yet --RR */ | ||
1449 | if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT)) { | 1514 | if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT)) { |
1450 | multiport = true; | 1515 | multiport = true; |
1451 | vdev->features[0] |= 1 << VIRTIO_CONSOLE_F_MULTIPORT; | 1516 | vdev->features[0] |= 1 << VIRTIO_CONSOLE_F_MULTIPORT; |
1452 | 1517 | ||
1453 | vdev->config->get(vdev, | 1518 | vdev->config->get(vdev, offsetof(struct virtio_console_config, |
1454 | offsetof(struct virtio_console_multiport_conf, | 1519 | max_nr_ports), |
1455 | nr_ports), | ||
1456 | &portdev->config.nr_ports, | ||
1457 | sizeof(portdev->config.nr_ports)); | ||
1458 | vdev->config->get(vdev, | ||
1459 | offsetof(struct virtio_console_multiport_conf, | ||
1460 | max_nr_ports), | ||
1461 | &portdev->config.max_nr_ports, | 1520 | &portdev->config.max_nr_ports, |
1462 | sizeof(portdev->config.max_nr_ports)); | 1521 | sizeof(portdev->config.max_nr_ports)); |
1463 | if (portdev->config.nr_ports > portdev->config.max_nr_ports) { | ||
1464 | dev_warn(&vdev->dev, | ||
1465 | "More ports (%u) specified than allowed (%u). Will init %u ports.", | ||
1466 | portdev->config.nr_ports, | ||
1467 | portdev->config.max_nr_ports, | ||
1468 | portdev->config.max_nr_ports); | ||
1469 | |||
1470 | portdev->config.nr_ports = portdev->config.max_nr_ports; | ||
1471 | } | ||
1472 | } | 1522 | } |
1473 | 1523 | ||
1474 | /* Let the Host know we support multiple ports.*/ | 1524 | /* Let the Host know we support multiple ports.*/ |
1475 | vdev->config->finalize_features(vdev); | 1525 | vdev->config->finalize_features(vdev); |
1476 | #endif | ||
1477 | 1526 | ||
1478 | err = init_vqs(portdev); | 1527 | err = init_vqs(portdev); |
1479 | if (err < 0) { | 1528 | if (err < 0) { |
@@ -1489,7 +1538,6 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) | |||
1489 | 1538 | ||
1490 | spin_lock_init(&portdev->cvq_lock); | 1539 | spin_lock_init(&portdev->cvq_lock); |
1491 | INIT_WORK(&portdev->control_work, &control_work_handler); | 1540 | INIT_WORK(&portdev->control_work, &control_work_handler); |
1492 | INIT_WORK(&portdev->config_work, &config_work_handler); | ||
1493 | 1541 | ||
1494 | nr_added_bufs = fill_queue(portdev->c_ivq, &portdev->cvq_lock); | 1542 | nr_added_bufs = fill_queue(portdev->c_ivq, &portdev->cvq_lock); |
1495 | if (!nr_added_bufs) { | 1543 | if (!nr_added_bufs) { |
@@ -1498,16 +1546,22 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) | |||
1498 | err = -ENOMEM; | 1546 | err = -ENOMEM; |
1499 | goto free_vqs; | 1547 | goto free_vqs; |
1500 | } | 1548 | } |
1549 | } else { | ||
1550 | /* | ||
1551 | * For backward compatibility: Create a console port | ||
1552 | * if we're running on older host. | ||
1553 | */ | ||
1554 | add_port(portdev, 0); | ||
1501 | } | 1555 | } |
1502 | 1556 | ||
1503 | for (i = 0; i < portdev->config.nr_ports; i++) | 1557 | __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID, |
1504 | add_port(portdev, i); | 1558 | VIRTIO_CONSOLE_DEVICE_READY, 1); |
1505 | |||
1506 | /* Start using the new console output. */ | ||
1507 | early_put_chars = NULL; | ||
1508 | return 0; | 1559 | return 0; |
1509 | 1560 | ||
1510 | free_vqs: | 1561 | free_vqs: |
1562 | /* The host might want to notify mgmt sw about device add failure */ | ||
1563 | __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID, | ||
1564 | VIRTIO_CONSOLE_DEVICE_READY, 0); | ||
1511 | vdev->config->del_vqs(vdev); | 1565 | vdev->config->del_vqs(vdev); |
1512 | kfree(portdev->in_vqs); | 1566 | kfree(portdev->in_vqs); |
1513 | kfree(portdev->out_vqs); | 1567 | kfree(portdev->out_vqs); |
@@ -1529,17 +1583,16 @@ static void virtcons_remove(struct virtio_device *vdev) | |||
1529 | portdev = vdev->priv; | 1583 | portdev = vdev->priv; |
1530 | 1584 | ||
1531 | cancel_work_sync(&portdev->control_work); | 1585 | cancel_work_sync(&portdev->control_work); |
1532 | cancel_work_sync(&portdev->config_work); | ||
1533 | 1586 | ||
1534 | list_for_each_entry_safe(port, port2, &portdev->ports, list) | 1587 | list_for_each_entry_safe(port, port2, &portdev->ports, list) |
1535 | remove_port(port); | 1588 | remove_port(port); |
1536 | 1589 | ||
1537 | unregister_chrdev(portdev->chr_major, "virtio-portsdev"); | 1590 | unregister_chrdev(portdev->chr_major, "virtio-portsdev"); |
1538 | 1591 | ||
1539 | while ((buf = portdev->c_ivq->vq_ops->get_buf(portdev->c_ivq, &len))) | 1592 | while ((buf = virtqueue_get_buf(portdev->c_ivq, &len))) |
1540 | free_buf(buf); | 1593 | free_buf(buf); |
1541 | 1594 | ||
1542 | while ((buf = portdev->c_ivq->vq_ops->detach_unused_buf(portdev->c_ivq))) | 1595 | while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq))) |
1543 | free_buf(buf); | 1596 | free_buf(buf); |
1544 | 1597 | ||
1545 | vdev->config->del_vqs(vdev); | 1598 | vdev->config->del_vqs(vdev); |
@@ -1556,6 +1609,7 @@ static struct virtio_device_id id_table[] = { | |||
1556 | 1609 | ||
1557 | static unsigned int features[] = { | 1610 | static unsigned int features[] = { |
1558 | VIRTIO_CONSOLE_F_SIZE, | 1611 | VIRTIO_CONSOLE_F_SIZE, |
1612 | VIRTIO_CONSOLE_F_MULTIPORT, | ||
1559 | }; | 1613 | }; |
1560 | 1614 | ||
1561 | static struct virtio_driver virtio_console = { | 1615 | static struct virtio_driver virtio_console = { |
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index b0a85d038796..78eb3190b9b1 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -122,7 +122,7 @@ static void skb_xmit_done(struct virtqueue *svq) | |||
122 | struct virtnet_info *vi = svq->vdev->priv; | 122 | struct virtnet_info *vi = svq->vdev->priv; |
123 | 123 | ||
124 | /* Suppress further interrupts. */ | 124 | /* Suppress further interrupts. */ |
125 | svq->vq_ops->disable_cb(svq); | 125 | virtqueue_disable_cb(svq); |
126 | 126 | ||
127 | /* We were probably waiting for more output buffers. */ | 127 | /* We were probably waiting for more output buffers. */ |
128 | netif_wake_queue(vi->dev); | 128 | netif_wake_queue(vi->dev); |
@@ -210,7 +210,7 @@ static int receive_mergeable(struct virtnet_info *vi, struct sk_buff *skb) | |||
210 | return -EINVAL; | 210 | return -EINVAL; |
211 | } | 211 | } |
212 | 212 | ||
213 | page = vi->rvq->vq_ops->get_buf(vi->rvq, &len); | 213 | page = virtqueue_get_buf(vi->rvq, &len); |
214 | if (!page) { | 214 | if (!page) { |
215 | pr_debug("%s: rx error: %d buffers missing\n", | 215 | pr_debug("%s: rx error: %d buffers missing\n", |
216 | skb->dev->name, hdr->mhdr.num_buffers); | 216 | skb->dev->name, hdr->mhdr.num_buffers); |
@@ -340,7 +340,7 @@ static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp) | |||
340 | 340 | ||
341 | skb_to_sgvec(skb, vi->rx_sg + 1, 0, skb->len); | 341 | skb_to_sgvec(skb, vi->rx_sg + 1, 0, skb->len); |
342 | 342 | ||
343 | err = vi->rvq->vq_ops->add_buf(vi->rvq, vi->rx_sg, 0, 2, skb); | 343 | err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, 2, skb); |
344 | if (err < 0) | 344 | if (err < 0) |
345 | dev_kfree_skb(skb); | 345 | dev_kfree_skb(skb); |
346 | 346 | ||
@@ -385,7 +385,7 @@ static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp) | |||
385 | 385 | ||
386 | /* chain first in list head */ | 386 | /* chain first in list head */ |
387 | first->private = (unsigned long)list; | 387 | first->private = (unsigned long)list; |
388 | err = vi->rvq->vq_ops->add_buf(vi->rvq, vi->rx_sg, 0, MAX_SKB_FRAGS + 2, | 388 | err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, MAX_SKB_FRAGS + 2, |
389 | first); | 389 | first); |
390 | if (err < 0) | 390 | if (err < 0) |
391 | give_pages(vi, first); | 391 | give_pages(vi, first); |
@@ -404,7 +404,7 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp) | |||
404 | 404 | ||
405 | sg_init_one(vi->rx_sg, page_address(page), PAGE_SIZE); | 405 | sg_init_one(vi->rx_sg, page_address(page), PAGE_SIZE); |
406 | 406 | ||
407 | err = vi->rvq->vq_ops->add_buf(vi->rvq, vi->rx_sg, 0, 1, page); | 407 | err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, 1, page); |
408 | if (err < 0) | 408 | if (err < 0) |
409 | give_pages(vi, page); | 409 | give_pages(vi, page); |
410 | 410 | ||
@@ -433,7 +433,7 @@ static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp) | |||
433 | } while (err > 0); | 433 | } while (err > 0); |
434 | if (unlikely(vi->num > vi->max)) | 434 | if (unlikely(vi->num > vi->max)) |
435 | vi->max = vi->num; | 435 | vi->max = vi->num; |
436 | vi->rvq->vq_ops->kick(vi->rvq); | 436 | virtqueue_kick(vi->rvq); |
437 | return !oom; | 437 | return !oom; |
438 | } | 438 | } |
439 | 439 | ||
@@ -442,7 +442,7 @@ static void skb_recv_done(struct virtqueue *rvq) | |||
442 | struct virtnet_info *vi = rvq->vdev->priv; | 442 | struct virtnet_info *vi = rvq->vdev->priv; |
443 | /* Schedule NAPI, Suppress further interrupts if successful. */ | 443 | /* Schedule NAPI, Suppress further interrupts if successful. */ |
444 | if (napi_schedule_prep(&vi->napi)) { | 444 | if (napi_schedule_prep(&vi->napi)) { |
445 | rvq->vq_ops->disable_cb(rvq); | 445 | virtqueue_disable_cb(rvq); |
446 | __napi_schedule(&vi->napi); | 446 | __napi_schedule(&vi->napi); |
447 | } | 447 | } |
448 | } | 448 | } |
@@ -471,7 +471,7 @@ static int virtnet_poll(struct napi_struct *napi, int budget) | |||
471 | 471 | ||
472 | again: | 472 | again: |
473 | while (received < budget && | 473 | while (received < budget && |
474 | (buf = vi->rvq->vq_ops->get_buf(vi->rvq, &len)) != NULL) { | 474 | (buf = virtqueue_get_buf(vi->rvq, &len)) != NULL) { |
475 | receive_buf(vi->dev, buf, len); | 475 | receive_buf(vi->dev, buf, len); |
476 | --vi->num; | 476 | --vi->num; |
477 | received++; | 477 | received++; |
@@ -485,9 +485,9 @@ again: | |||
485 | /* Out of packets? */ | 485 | /* Out of packets? */ |
486 | if (received < budget) { | 486 | if (received < budget) { |
487 | napi_complete(napi); | 487 | napi_complete(napi); |
488 | if (unlikely(!vi->rvq->vq_ops->enable_cb(vi->rvq)) && | 488 | if (unlikely(!virtqueue_enable_cb(vi->rvq)) && |
489 | napi_schedule_prep(napi)) { | 489 | napi_schedule_prep(napi)) { |
490 | vi->rvq->vq_ops->disable_cb(vi->rvq); | 490 | virtqueue_disable_cb(vi->rvq); |
491 | __napi_schedule(napi); | 491 | __napi_schedule(napi); |
492 | goto again; | 492 | goto again; |
493 | } | 493 | } |
@@ -501,7 +501,7 @@ static unsigned int free_old_xmit_skbs(struct virtnet_info *vi) | |||
501 | struct sk_buff *skb; | 501 | struct sk_buff *skb; |
502 | unsigned int len, tot_sgs = 0; | 502 | unsigned int len, tot_sgs = 0; |
503 | 503 | ||
504 | while ((skb = vi->svq->vq_ops->get_buf(vi->svq, &len)) != NULL) { | 504 | while ((skb = virtqueue_get_buf(vi->svq, &len)) != NULL) { |
505 | pr_debug("Sent skb %p\n", skb); | 505 | pr_debug("Sent skb %p\n", skb); |
506 | vi->dev->stats.tx_bytes += skb->len; | 506 | vi->dev->stats.tx_bytes += skb->len; |
507 | vi->dev->stats.tx_packets++; | 507 | vi->dev->stats.tx_packets++; |
@@ -554,7 +554,7 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) | |||
554 | sg_set_buf(vi->tx_sg, &hdr->hdr, sizeof hdr->hdr); | 554 | sg_set_buf(vi->tx_sg, &hdr->hdr, sizeof hdr->hdr); |
555 | 555 | ||
556 | hdr->num_sg = skb_to_sgvec(skb, vi->tx_sg + 1, 0, skb->len) + 1; | 556 | hdr->num_sg = skb_to_sgvec(skb, vi->tx_sg + 1, 0, skb->len) + 1; |
557 | return vi->svq->vq_ops->add_buf(vi->svq, vi->tx_sg, hdr->num_sg, | 557 | return virtqueue_add_buf(vi->svq, vi->tx_sg, hdr->num_sg, |
558 | 0, skb); | 558 | 0, skb); |
559 | } | 559 | } |
560 | 560 | ||
@@ -574,14 +574,14 @@ again: | |||
574 | if (unlikely(capacity < 0)) { | 574 | if (unlikely(capacity < 0)) { |
575 | netif_stop_queue(dev); | 575 | netif_stop_queue(dev); |
576 | dev_warn(&dev->dev, "Unexpected full queue\n"); | 576 | dev_warn(&dev->dev, "Unexpected full queue\n"); |
577 | if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) { | 577 | if (unlikely(!virtqueue_enable_cb(vi->svq))) { |
578 | vi->svq->vq_ops->disable_cb(vi->svq); | 578 | virtqueue_disable_cb(vi->svq); |
579 | netif_start_queue(dev); | 579 | netif_start_queue(dev); |
580 | goto again; | 580 | goto again; |
581 | } | 581 | } |
582 | return NETDEV_TX_BUSY; | 582 | return NETDEV_TX_BUSY; |
583 | } | 583 | } |
584 | vi->svq->vq_ops->kick(vi->svq); | 584 | virtqueue_kick(vi->svq); |
585 | 585 | ||
586 | /* Don't wait up for transmitted skbs to be freed. */ | 586 | /* Don't wait up for transmitted skbs to be freed. */ |
587 | skb_orphan(skb); | 587 | skb_orphan(skb); |
@@ -591,12 +591,12 @@ again: | |||
591 | * before it gets out of hand. Naturally, this wastes entries. */ | 591 | * before it gets out of hand. Naturally, this wastes entries. */ |
592 | if (capacity < 2+MAX_SKB_FRAGS) { | 592 | if (capacity < 2+MAX_SKB_FRAGS) { |
593 | netif_stop_queue(dev); | 593 | netif_stop_queue(dev); |
594 | if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) { | 594 | if (unlikely(!virtqueue_enable_cb(vi->svq))) { |
595 | /* More just got used, free them then recheck. */ | 595 | /* More just got used, free them then recheck. */ |
596 | capacity += free_old_xmit_skbs(vi); | 596 | capacity += free_old_xmit_skbs(vi); |
597 | if (capacity >= 2+MAX_SKB_FRAGS) { | 597 | if (capacity >= 2+MAX_SKB_FRAGS) { |
598 | netif_start_queue(dev); | 598 | netif_start_queue(dev); |
599 | vi->svq->vq_ops->disable_cb(vi->svq); | 599 | virtqueue_disable_cb(vi->svq); |
600 | } | 600 | } |
601 | } | 601 | } |
602 | } | 602 | } |
@@ -641,7 +641,7 @@ static int virtnet_open(struct net_device *dev) | |||
641 | * now. virtnet_poll wants re-enable the queue, so we disable here. | 641 | * now. virtnet_poll wants re-enable the queue, so we disable here. |
642 | * We synchronize against interrupts via NAPI_STATE_SCHED */ | 642 | * We synchronize against interrupts via NAPI_STATE_SCHED */ |
643 | if (napi_schedule_prep(&vi->napi)) { | 643 | if (napi_schedule_prep(&vi->napi)) { |
644 | vi->rvq->vq_ops->disable_cb(vi->rvq); | 644 | virtqueue_disable_cb(vi->rvq); |
645 | __napi_schedule(&vi->napi); | 645 | __napi_schedule(&vi->napi); |
646 | } | 646 | } |
647 | return 0; | 647 | return 0; |
@@ -678,15 +678,15 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, | |||
678 | sg_set_buf(&sg[i + 1], sg_virt(s), s->length); | 678 | sg_set_buf(&sg[i + 1], sg_virt(s), s->length); |
679 | sg_set_buf(&sg[out + in - 1], &status, sizeof(status)); | 679 | sg_set_buf(&sg[out + in - 1], &status, sizeof(status)); |
680 | 680 | ||
681 | BUG_ON(vi->cvq->vq_ops->add_buf(vi->cvq, sg, out, in, vi) < 0); | 681 | BUG_ON(virtqueue_add_buf(vi->cvq, sg, out, in, vi) < 0); |
682 | 682 | ||
683 | vi->cvq->vq_ops->kick(vi->cvq); | 683 | virtqueue_kick(vi->cvq); |
684 | 684 | ||
685 | /* | 685 | /* |
686 | * Spin for a response, the kick causes an ioport write, trapping | 686 | * Spin for a response, the kick causes an ioport write, trapping |
687 | * into the hypervisor, so the request should be handled immediately. | 687 | * into the hypervisor, so the request should be handled immediately. |
688 | */ | 688 | */ |
689 | while (!vi->cvq->vq_ops->get_buf(vi->cvq, &tmp)) | 689 | while (!virtqueue_get_buf(vi->cvq, &tmp)) |
690 | cpu_relax(); | 690 | cpu_relax(); |
691 | 691 | ||
692 | return status == VIRTIO_NET_OK; | 692 | return status == VIRTIO_NET_OK; |
@@ -1003,13 +1003,13 @@ static void free_unused_bufs(struct virtnet_info *vi) | |||
1003 | { | 1003 | { |
1004 | void *buf; | 1004 | void *buf; |
1005 | while (1) { | 1005 | while (1) { |
1006 | buf = vi->svq->vq_ops->detach_unused_buf(vi->svq); | 1006 | buf = virtqueue_detach_unused_buf(vi->svq); |
1007 | if (!buf) | 1007 | if (!buf) |
1008 | break; | 1008 | break; |
1009 | dev_kfree_skb(buf); | 1009 | dev_kfree_skb(buf); |
1010 | } | 1010 | } |
1011 | while (1) { | 1011 | while (1) { |
1012 | buf = vi->rvq->vq_ops->detach_unused_buf(vi->rvq); | 1012 | buf = virtqueue_detach_unused_buf(vi->rvq); |
1013 | if (!buf) | 1013 | if (!buf) |
1014 | break; | 1014 | break; |
1015 | if (vi->mergeable_rx_bufs || vi->big_packets) | 1015 | if (vi->mergeable_rx_bufs || vi->big_packets) |
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index bfec7c29486d..0f1da45ba47d 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c | |||
@@ -75,7 +75,7 @@ static void balloon_ack(struct virtqueue *vq) | |||
75 | struct virtio_balloon *vb; | 75 | struct virtio_balloon *vb; |
76 | unsigned int len; | 76 | unsigned int len; |
77 | 77 | ||
78 | vb = vq->vq_ops->get_buf(vq, &len); | 78 | vb = virtqueue_get_buf(vq, &len); |
79 | if (vb) | 79 | if (vb) |
80 | complete(&vb->acked); | 80 | complete(&vb->acked); |
81 | } | 81 | } |
@@ -89,9 +89,9 @@ static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq) | |||
89 | init_completion(&vb->acked); | 89 | init_completion(&vb->acked); |
90 | 90 | ||
91 | /* We should always be able to add one buffer to an empty queue. */ | 91 | /* We should always be able to add one buffer to an empty queue. */ |
92 | if (vq->vq_ops->add_buf(vq, &sg, 1, 0, vb) < 0) | 92 | if (virtqueue_add_buf(vq, &sg, 1, 0, vb) < 0) |
93 | BUG(); | 93 | BUG(); |
94 | vq->vq_ops->kick(vq); | 94 | virtqueue_kick(vq); |
95 | 95 | ||
96 | /* When host has read buffer, this completes via balloon_ack */ | 96 | /* When host has read buffer, this completes via balloon_ack */ |
97 | wait_for_completion(&vb->acked); | 97 | wait_for_completion(&vb->acked); |
@@ -204,7 +204,7 @@ static void stats_request(struct virtqueue *vq) | |||
204 | struct virtio_balloon *vb; | 204 | struct virtio_balloon *vb; |
205 | unsigned int len; | 205 | unsigned int len; |
206 | 206 | ||
207 | vb = vq->vq_ops->get_buf(vq, &len); | 207 | vb = virtqueue_get_buf(vq, &len); |
208 | if (!vb) | 208 | if (!vb) |
209 | return; | 209 | return; |
210 | vb->need_stats_update = 1; | 210 | vb->need_stats_update = 1; |
@@ -221,9 +221,9 @@ static void stats_handle_request(struct virtio_balloon *vb) | |||
221 | 221 | ||
222 | vq = vb->stats_vq; | 222 | vq = vb->stats_vq; |
223 | sg_init_one(&sg, vb->stats, sizeof(vb->stats)); | 223 | sg_init_one(&sg, vb->stats, sizeof(vb->stats)); |
224 | if (vq->vq_ops->add_buf(vq, &sg, 1, 0, vb) < 0) | 224 | if (virtqueue_add_buf(vq, &sg, 1, 0, vb) < 0) |
225 | BUG(); | 225 | BUG(); |
226 | vq->vq_ops->kick(vq); | 226 | virtqueue_kick(vq); |
227 | } | 227 | } |
228 | 228 | ||
229 | static void virtballoon_changed(struct virtio_device *vdev) | 229 | static void virtballoon_changed(struct virtio_device *vdev) |
@@ -314,10 +314,9 @@ static int virtballoon_probe(struct virtio_device *vdev) | |||
314 | * use it to signal us later. | 314 | * use it to signal us later. |
315 | */ | 315 | */ |
316 | sg_init_one(&sg, vb->stats, sizeof vb->stats); | 316 | sg_init_one(&sg, vb->stats, sizeof vb->stats); |
317 | if (vb->stats_vq->vq_ops->add_buf(vb->stats_vq, | 317 | if (virtqueue_add_buf(vb->stats_vq, &sg, 1, 0, vb) < 0) |
318 | &sg, 1, 0, vb) < 0) | ||
319 | BUG(); | 318 | BUG(); |
320 | vb->stats_vq->vq_ops->kick(vb->stats_vq); | 319 | virtqueue_kick(vb->stats_vq); |
321 | } | 320 | } |
322 | 321 | ||
323 | vb->thread = kthread_run(balloon, vb, "vballoon"); | 322 | vb->thread = kthread_run(balloon, vb, "vballoon"); |
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 0f90634bcb85..1ca88908723b 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c | |||
@@ -110,13 +110,14 @@ struct vring_virtqueue | |||
110 | static int vring_add_indirect(struct vring_virtqueue *vq, | 110 | static int vring_add_indirect(struct vring_virtqueue *vq, |
111 | struct scatterlist sg[], | 111 | struct scatterlist sg[], |
112 | unsigned int out, | 112 | unsigned int out, |
113 | unsigned int in) | 113 | unsigned int in, |
114 | gfp_t gfp) | ||
114 | { | 115 | { |
115 | struct vring_desc *desc; | 116 | struct vring_desc *desc; |
116 | unsigned head; | 117 | unsigned head; |
117 | int i; | 118 | int i; |
118 | 119 | ||
119 | desc = kmalloc((out + in) * sizeof(struct vring_desc), GFP_ATOMIC); | 120 | desc = kmalloc((out + in) * sizeof(struct vring_desc), gfp); |
120 | if (!desc) | 121 | if (!desc) |
121 | return vq->vring.num; | 122 | return vq->vring.num; |
122 | 123 | ||
@@ -155,11 +156,12 @@ static int vring_add_indirect(struct vring_virtqueue *vq, | |||
155 | return head; | 156 | return head; |
156 | } | 157 | } |
157 | 158 | ||
158 | static int vring_add_buf(struct virtqueue *_vq, | 159 | int virtqueue_add_buf_gfp(struct virtqueue *_vq, |
159 | struct scatterlist sg[], | 160 | struct scatterlist sg[], |
160 | unsigned int out, | 161 | unsigned int out, |
161 | unsigned int in, | 162 | unsigned int in, |
162 | void *data) | 163 | void *data, |
164 | gfp_t gfp) | ||
163 | { | 165 | { |
164 | struct vring_virtqueue *vq = to_vvq(_vq); | 166 | struct vring_virtqueue *vq = to_vvq(_vq); |
165 | unsigned int i, avail, head, uninitialized_var(prev); | 167 | unsigned int i, avail, head, uninitialized_var(prev); |
@@ -171,7 +173,7 @@ static int vring_add_buf(struct virtqueue *_vq, | |||
171 | /* If the host supports indirect descriptor tables, and we have multiple | 173 | /* If the host supports indirect descriptor tables, and we have multiple |
172 | * buffers, then go indirect. FIXME: tune this threshold */ | 174 | * buffers, then go indirect. FIXME: tune this threshold */ |
173 | if (vq->indirect && (out + in) > 1 && vq->num_free) { | 175 | if (vq->indirect && (out + in) > 1 && vq->num_free) { |
174 | head = vring_add_indirect(vq, sg, out, in); | 176 | head = vring_add_indirect(vq, sg, out, in, gfp); |
175 | if (head != vq->vring.num) | 177 | if (head != vq->vring.num) |
176 | goto add_head; | 178 | goto add_head; |
177 | } | 179 | } |
@@ -232,8 +234,9 @@ add_head: | |||
232 | return vq->num_free ? vq->vring.num : 0; | 234 | return vq->num_free ? vq->vring.num : 0; |
233 | return vq->num_free; | 235 | return vq->num_free; |
234 | } | 236 | } |
237 | EXPORT_SYMBOL_GPL(virtqueue_add_buf_gfp); | ||
235 | 238 | ||
236 | static void vring_kick(struct virtqueue *_vq) | 239 | void virtqueue_kick(struct virtqueue *_vq) |
237 | { | 240 | { |
238 | struct vring_virtqueue *vq = to_vvq(_vq); | 241 | struct vring_virtqueue *vq = to_vvq(_vq); |
239 | START_USE(vq); | 242 | START_USE(vq); |
@@ -253,6 +256,7 @@ static void vring_kick(struct virtqueue *_vq) | |||
253 | 256 | ||
254 | END_USE(vq); | 257 | END_USE(vq); |
255 | } | 258 | } |
259 | EXPORT_SYMBOL_GPL(virtqueue_kick); | ||
256 | 260 | ||
257 | static void detach_buf(struct vring_virtqueue *vq, unsigned int head) | 261 | static void detach_buf(struct vring_virtqueue *vq, unsigned int head) |
258 | { | 262 | { |
@@ -284,7 +288,7 @@ static inline bool more_used(const struct vring_virtqueue *vq) | |||
284 | return vq->last_used_idx != vq->vring.used->idx; | 288 | return vq->last_used_idx != vq->vring.used->idx; |
285 | } | 289 | } |
286 | 290 | ||
287 | static void *vring_get_buf(struct virtqueue *_vq, unsigned int *len) | 291 | void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len) |
288 | { | 292 | { |
289 | struct vring_virtqueue *vq = to_vvq(_vq); | 293 | struct vring_virtqueue *vq = to_vvq(_vq); |
290 | void *ret; | 294 | void *ret; |
@@ -325,15 +329,17 @@ static void *vring_get_buf(struct virtqueue *_vq, unsigned int *len) | |||
325 | END_USE(vq); | 329 | END_USE(vq); |
326 | return ret; | 330 | return ret; |
327 | } | 331 | } |
332 | EXPORT_SYMBOL_GPL(virtqueue_get_buf); | ||
328 | 333 | ||
329 | static void vring_disable_cb(struct virtqueue *_vq) | 334 | void virtqueue_disable_cb(struct virtqueue *_vq) |
330 | { | 335 | { |
331 | struct vring_virtqueue *vq = to_vvq(_vq); | 336 | struct vring_virtqueue *vq = to_vvq(_vq); |
332 | 337 | ||
333 | vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; | 338 | vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; |
334 | } | 339 | } |
340 | EXPORT_SYMBOL_GPL(virtqueue_disable_cb); | ||
335 | 341 | ||
336 | static bool vring_enable_cb(struct virtqueue *_vq) | 342 | bool virtqueue_enable_cb(struct virtqueue *_vq) |
337 | { | 343 | { |
338 | struct vring_virtqueue *vq = to_vvq(_vq); | 344 | struct vring_virtqueue *vq = to_vvq(_vq); |
339 | 345 | ||
@@ -351,8 +357,9 @@ static bool vring_enable_cb(struct virtqueue *_vq) | |||
351 | END_USE(vq); | 357 | END_USE(vq); |
352 | return true; | 358 | return true; |
353 | } | 359 | } |
360 | EXPORT_SYMBOL_GPL(virtqueue_enable_cb); | ||
354 | 361 | ||
355 | static void *vring_detach_unused_buf(struct virtqueue *_vq) | 362 | void *virtqueue_detach_unused_buf(struct virtqueue *_vq) |
356 | { | 363 | { |
357 | struct vring_virtqueue *vq = to_vvq(_vq); | 364 | struct vring_virtqueue *vq = to_vvq(_vq); |
358 | unsigned int i; | 365 | unsigned int i; |
@@ -375,6 +382,7 @@ static void *vring_detach_unused_buf(struct virtqueue *_vq) | |||
375 | END_USE(vq); | 382 | END_USE(vq); |
376 | return NULL; | 383 | return NULL; |
377 | } | 384 | } |
385 | EXPORT_SYMBOL_GPL(virtqueue_detach_unused_buf); | ||
378 | 386 | ||
379 | irqreturn_t vring_interrupt(int irq, void *_vq) | 387 | irqreturn_t vring_interrupt(int irq, void *_vq) |
380 | { | 388 | { |
@@ -396,15 +404,6 @@ irqreturn_t vring_interrupt(int irq, void *_vq) | |||
396 | } | 404 | } |
397 | EXPORT_SYMBOL_GPL(vring_interrupt); | 405 | EXPORT_SYMBOL_GPL(vring_interrupt); |
398 | 406 | ||
399 | static struct virtqueue_ops vring_vq_ops = { | ||
400 | .add_buf = vring_add_buf, | ||
401 | .get_buf = vring_get_buf, | ||
402 | .kick = vring_kick, | ||
403 | .disable_cb = vring_disable_cb, | ||
404 | .enable_cb = vring_enable_cb, | ||
405 | .detach_unused_buf = vring_detach_unused_buf, | ||
406 | }; | ||
407 | |||
408 | struct virtqueue *vring_new_virtqueue(unsigned int num, | 407 | struct virtqueue *vring_new_virtqueue(unsigned int num, |
409 | unsigned int vring_align, | 408 | unsigned int vring_align, |
410 | struct virtio_device *vdev, | 409 | struct virtio_device *vdev, |
@@ -429,7 +428,6 @@ struct virtqueue *vring_new_virtqueue(unsigned int num, | |||
429 | vring_init(&vq->vring, num, pages, vring_align); | 428 | vring_init(&vq->vring, num, pages, vring_align); |
430 | vq->vq.callback = callback; | 429 | vq->vq.callback = callback; |
431 | vq->vq.vdev = vdev; | 430 | vq->vq.vdev = vdev; |
432 | vq->vq.vq_ops = &vring_vq_ops; | ||
433 | vq->vq.name = name; | 431 | vq->vq.name = name; |
434 | vq->notify = notify; | 432 | vq->notify = notify; |
435 | vq->broken = false; | 433 | vq->broken = false; |
diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 40d1709bdbf4..aff5b4f74041 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/spinlock.h> | 7 | #include <linux/spinlock.h> |
8 | #include <linux/device.h> | 8 | #include <linux/device.h> |
9 | #include <linux/mod_devicetable.h> | 9 | #include <linux/mod_devicetable.h> |
10 | #include <linux/gfp.h> | ||
10 | 11 | ||
11 | /** | 12 | /** |
12 | * virtqueue - a queue to register buffers for sending or receiving. | 13 | * virtqueue - a queue to register buffers for sending or receiving. |
@@ -14,7 +15,6 @@ | |||
14 | * @callback: the function to call when buffers are consumed (can be NULL). | 15 | * @callback: the function to call when buffers are consumed (can be NULL). |
15 | * @name: the name of this virtqueue (mainly for debugging) | 16 | * @name: the name of this virtqueue (mainly for debugging) |
16 | * @vdev: the virtio device this queue was created for. | 17 | * @vdev: the virtio device this queue was created for. |
17 | * @vq_ops: the operations for this virtqueue (see below). | ||
18 | * @priv: a pointer for the virtqueue implementation to use. | 18 | * @priv: a pointer for the virtqueue implementation to use. |
19 | */ | 19 | */ |
20 | struct virtqueue { | 20 | struct virtqueue { |
@@ -22,60 +22,71 @@ struct virtqueue { | |||
22 | void (*callback)(struct virtqueue *vq); | 22 | void (*callback)(struct virtqueue *vq); |
23 | const char *name; | 23 | const char *name; |
24 | struct virtio_device *vdev; | 24 | struct virtio_device *vdev; |
25 | struct virtqueue_ops *vq_ops; | ||
26 | void *priv; | 25 | void *priv; |
27 | }; | 26 | }; |
28 | 27 | ||
29 | /** | 28 | /** |
30 | * virtqueue_ops - operations for virtqueue abstraction layer | 29 | * operations for virtqueue |
31 | * @add_buf: expose buffer to other end | 30 | * virtqueue_add_buf: expose buffer to other end |
32 | * vq: the struct virtqueue we're talking about. | 31 | * vq: the struct virtqueue we're talking about. |
33 | * sg: the description of the buffer(s). | 32 | * sg: the description of the buffer(s). |
34 | * out_num: the number of sg readable by other side | 33 | * out_num: the number of sg readable by other side |
35 | * in_num: the number of sg which are writable (after readable ones) | 34 | * in_num: the number of sg which are writable (after readable ones) |
36 | * data: the token identifying the buffer. | 35 | * data: the token identifying the buffer. |
36 | * gfp: how to do memory allocations (if necessary). | ||
37 | * Returns remaining capacity of queue (sg segments) or a negative error. | 37 | * Returns remaining capacity of queue (sg segments) or a negative error. |
38 | * @kick: update after add_buf | 38 | * virtqueue_kick: update after add_buf |
39 | * vq: the struct virtqueue | 39 | * vq: the struct virtqueue |
40 | * After one or more add_buf calls, invoke this to kick the other side. | 40 | * After one or more add_buf calls, invoke this to kick the other side. |
41 | * @get_buf: get the next used buffer | 41 | * virtqueue_get_buf: get the next used buffer |
42 | * vq: the struct virtqueue we're talking about. | 42 | * vq: the struct virtqueue we're talking about. |
43 | * len: the length written into the buffer | 43 | * len: the length written into the buffer |
44 | * Returns NULL or the "data" token handed to add_buf. | 44 | * Returns NULL or the "data" token handed to add_buf. |
45 | * @disable_cb: disable callbacks | 45 | * virtqueue_disable_cb: disable callbacks |
46 | * vq: the struct virtqueue we're talking about. | 46 | * vq: the struct virtqueue we're talking about. |
47 | * Note that this is not necessarily synchronous, hence unreliable and only | 47 | * Note that this is not necessarily synchronous, hence unreliable and only |
48 | * useful as an optimization. | 48 | * useful as an optimization. |
49 | * @enable_cb: restart callbacks after disable_cb. | 49 | * virtqueue_enable_cb: restart callbacks after disable_cb. |
50 | * vq: the struct virtqueue we're talking about. | 50 | * vq: the struct virtqueue we're talking about. |
51 | * This re-enables callbacks; it returns "false" if there are pending | 51 | * This re-enables callbacks; it returns "false" if there are pending |
52 | * buffers in the queue, to detect a possible race between the driver | 52 | * buffers in the queue, to detect a possible race between the driver |
53 | * checking for more work, and enabling callbacks. | 53 | * checking for more work, and enabling callbacks. |
54 | * @detach_unused_buf: detach first unused buffer | 54 | * virtqueue_detach_unused_buf: detach first unused buffer |
55 | * vq: the struct virtqueue we're talking about. | 55 | * vq: the struct virtqueue we're talking about. |
56 | * Returns NULL or the "data" token handed to add_buf | 56 | * Returns NULL or the "data" token handed to add_buf |
57 | * | 57 | * |
58 | * Locking rules are straightforward: the driver is responsible for | 58 | * Locking rules are straightforward: the driver is responsible for |
59 | * locking. No two operations may be invoked simultaneously, with the exception | 59 | * locking. No two operations may be invoked simultaneously, with the exception |
60 | * of @disable_cb. | 60 | * of virtqueue_disable_cb. |
61 | * | 61 | * |
62 | * All operations can be called in any context. | 62 | * All operations can be called in any context. |
63 | */ | 63 | */ |
64 | struct virtqueue_ops { | ||
65 | int (*add_buf)(struct virtqueue *vq, | ||
66 | struct scatterlist sg[], | ||
67 | unsigned int out_num, | ||
68 | unsigned int in_num, | ||
69 | void *data); | ||
70 | 64 | ||
71 | void (*kick)(struct virtqueue *vq); | 65 | int virtqueue_add_buf_gfp(struct virtqueue *vq, |
66 | struct scatterlist sg[], | ||
67 | unsigned int out_num, | ||
68 | unsigned int in_num, | ||
69 | void *data, | ||
70 | gfp_t gfp); | ||
72 | 71 | ||
73 | void *(*get_buf)(struct virtqueue *vq, unsigned int *len); | 72 | static inline int virtqueue_add_buf(struct virtqueue *vq, |
73 | struct scatterlist sg[], | ||
74 | unsigned int out_num, | ||
75 | unsigned int in_num, | ||
76 | void *data) | ||
77 | { | ||
78 | return virtqueue_add_buf_gfp(vq, sg, out_num, in_num, data, GFP_ATOMIC); | ||
79 | } | ||
74 | 80 | ||
75 | void (*disable_cb)(struct virtqueue *vq); | 81 | void virtqueue_kick(struct virtqueue *vq); |
76 | bool (*enable_cb)(struct virtqueue *vq); | 82 | |
77 | void *(*detach_unused_buf)(struct virtqueue *vq); | 83 | void *virtqueue_get_buf(struct virtqueue *vq, unsigned int *len); |
78 | }; | 84 | |
85 | void virtqueue_disable_cb(struct virtqueue *vq); | ||
86 | |||
87 | bool virtqueue_enable_cb(struct virtqueue *vq); | ||
88 | |||
89 | void *virtqueue_detach_unused_buf(struct virtqueue *vq); | ||
79 | 90 | ||
80 | /** | 91 | /** |
81 | * virtio_device - representation of a device using virtio | 92 | * virtio_device - representation of a device using virtio |
diff --git a/include/linux/virtio_blk.h b/include/linux/virtio_blk.h index e52029e98919..167720d695ed 100644 --- a/include/linux/virtio_blk.h +++ b/include/linux/virtio_blk.h | |||
@@ -17,6 +17,8 @@ | |||
17 | #define VIRTIO_BLK_F_FLUSH 9 /* Cache flush command support */ | 17 | #define VIRTIO_BLK_F_FLUSH 9 /* Cache flush command support */ |
18 | #define VIRTIO_BLK_F_TOPOLOGY 10 /* Topology information is available */ | 18 | #define VIRTIO_BLK_F_TOPOLOGY 10 /* Topology information is available */ |
19 | 19 | ||
20 | #define VIRTIO_BLK_ID_BYTES 20 /* ID string length */ | ||
21 | |||
20 | struct virtio_blk_config { | 22 | struct virtio_blk_config { |
21 | /* The capacity (in 512-byte sectors). */ | 23 | /* The capacity (in 512-byte sectors). */ |
22 | __u64 capacity; | 24 | __u64 capacity; |
@@ -67,6 +69,9 @@ struct virtio_blk_config { | |||
67 | /* Cache flush command */ | 69 | /* Cache flush command */ |
68 | #define VIRTIO_BLK_T_FLUSH 4 | 70 | #define VIRTIO_BLK_T_FLUSH 4 |
69 | 71 | ||
72 | /* Get device ID command */ | ||
73 | #define VIRTIO_BLK_T_GET_ID 8 | ||
74 | |||
70 | /* Barrier before this op. */ | 75 | /* Barrier before this op. */ |
71 | #define VIRTIO_BLK_T_BARRIER 0x80000000 | 76 | #define VIRTIO_BLK_T_BARRIER 0x80000000 |
72 | 77 | ||
diff --git a/include/linux/virtio_console.h b/include/linux/virtio_console.h index 92228a8fbcbc..a85064db8f94 100644 --- a/include/linux/virtio_console.h +++ b/include/linux/virtio_console.h | |||
@@ -12,14 +12,39 @@ | |||
12 | 12 | ||
13 | /* Feature bits */ | 13 | /* Feature bits */ |
14 | #define VIRTIO_CONSOLE_F_SIZE 0 /* Does host provide console size? */ | 14 | #define VIRTIO_CONSOLE_F_SIZE 0 /* Does host provide console size? */ |
15 | #define VIRTIO_CONSOLE_F_MULTIPORT 1 /* Does host provide multiple ports? */ | ||
16 | |||
17 | #define VIRTIO_CONSOLE_BAD_ID (~(u32)0) | ||
15 | 18 | ||
16 | struct virtio_console_config { | 19 | struct virtio_console_config { |
17 | /* colums of the screens */ | 20 | /* colums of the screens */ |
18 | __u16 cols; | 21 | __u16 cols; |
19 | /* rows of the screens */ | 22 | /* rows of the screens */ |
20 | __u16 rows; | 23 | __u16 rows; |
24 | /* max. number of ports this device can hold */ | ||
25 | __u32 max_nr_ports; | ||
21 | } __attribute__((packed)); | 26 | } __attribute__((packed)); |
22 | 27 | ||
28 | /* | ||
29 | * A message that's passed between the Host and the Guest for a | ||
30 | * particular port. | ||
31 | */ | ||
32 | struct virtio_console_control { | ||
33 | __u32 id; /* Port number */ | ||
34 | __u16 event; /* The kind of control event (see below) */ | ||
35 | __u16 value; /* Extra information for the key */ | ||
36 | }; | ||
37 | |||
38 | /* Some events for control messages */ | ||
39 | #define VIRTIO_CONSOLE_DEVICE_READY 0 | ||
40 | #define VIRTIO_CONSOLE_PORT_ADD 1 | ||
41 | #define VIRTIO_CONSOLE_PORT_REMOVE 2 | ||
42 | #define VIRTIO_CONSOLE_PORT_READY 3 | ||
43 | #define VIRTIO_CONSOLE_CONSOLE_PORT 4 | ||
44 | #define VIRTIO_CONSOLE_RESIZE 5 | ||
45 | #define VIRTIO_CONSOLE_PORT_OPEN 6 | ||
46 | #define VIRTIO_CONSOLE_PORT_NAME 7 | ||
47 | |||
23 | #ifdef __KERNEL__ | 48 | #ifdef __KERNEL__ |
24 | int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)); | 49 | int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)); |
25 | #endif /* __KERNEL__ */ | 50 | #endif /* __KERNEL__ */ |
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 7eb78ecc1618..dcfbe99ff81c 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c | |||
@@ -137,7 +137,7 @@ static void req_done(struct virtqueue *vq) | |||
137 | 137 | ||
138 | P9_DPRINTK(P9_DEBUG_TRANS, ": request done\n"); | 138 | P9_DPRINTK(P9_DEBUG_TRANS, ": request done\n"); |
139 | 139 | ||
140 | while ((rc = chan->vq->vq_ops->get_buf(chan->vq, &len)) != NULL) { | 140 | while ((rc = virtqueue_get_buf(chan->vq, &len)) != NULL) { |
141 | P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc); | 141 | P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc); |
142 | P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag); | 142 | P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag); |
143 | req = p9_tag_lookup(chan->client, rc->tag); | 143 | req = p9_tag_lookup(chan->client, rc->tag); |
@@ -209,13 +209,13 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req) | |||
209 | 209 | ||
210 | req->status = REQ_STATUS_SENT; | 210 | req->status = REQ_STATUS_SENT; |
211 | 211 | ||
212 | if (chan->vq->vq_ops->add_buf(chan->vq, chan->sg, out, in, req->tc) < 0) { | 212 | if (virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc) < 0) { |
213 | P9_DPRINTK(P9_DEBUG_TRANS, | 213 | P9_DPRINTK(P9_DEBUG_TRANS, |
214 | "9p debug: virtio rpc add_buf returned failure"); | 214 | "9p debug: virtio rpc add_buf returned failure"); |
215 | return -EIO; | 215 | return -EIO; |
216 | } | 216 | } |
217 | 217 | ||
218 | chan->vq->vq_ops->kick(chan->vq); | 218 | virtqueue_kick(chan->vq); |
219 | 219 | ||
220 | P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request kicked\n"); | 220 | P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request kicked\n"); |
221 | return 0; | 221 | return 0; |