diff options
| -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; |
