diff options
Diffstat (limited to 'drivers/scsi/virtio_scsi.c')
-rw-r--r-- | drivers/scsi/virtio_scsi.c | 78 |
1 files changed, 13 insertions, 65 deletions
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index db3b494e5926..d4727b339474 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c | |||
@@ -73,17 +73,12 @@ struct virtio_scsi_vq { | |||
73 | * queue, and also lets the driver optimize the IRQ affinity for the virtqueues | 73 | * queue, and also lets the driver optimize the IRQ affinity for the virtqueues |
74 | * (each virtqueue's affinity is set to the CPU that "owns" the queue). | 74 | * (each virtqueue's affinity is set to the CPU that "owns" the queue). |
75 | * | 75 | * |
76 | * An interesting effect of this policy is that only writes to req_vq need to | 76 | * tgt_lock is held to serialize reading and writing req_vq. Reading req_vq |
77 | * take the tgt_lock. Read can be done outside the lock because: | 77 | * could be done locklessly, but we do not do it yet. |
78 | * | 78 | * |
79 | * - writes of req_vq only occur when atomic_inc_return(&tgt->reqs) returns 1. | 79 | * Decrements of reqs are never concurrent with writes of req_vq: before the |
80 | * In that case, no other CPU is reading req_vq: even if they were in | 80 | * decrement reqs will be != 0; after the decrement the virtqueue completion |
81 | * virtscsi_queuecommand_multi, they would be spinning on tgt_lock. | 81 | * routine will not use the req_vq so it can be changed by a new request. |
82 | * | ||
83 | * - reads of req_vq only occur when the target is not idle (reqs != 0). | ||
84 | * A CPU that enters virtscsi_queuecommand_multi will not modify req_vq. | ||
85 | * | ||
86 | * Similarly, decrements of reqs are never concurrent with writes of req_vq. | ||
87 | * Thus they can happen outside the tgt_lock, provided of course we make reqs | 82 | * Thus they can happen outside the tgt_lock, provided of course we make reqs |
88 | * an atomic_t. | 83 | * an atomic_t. |
89 | */ | 84 | */ |
@@ -204,7 +199,6 @@ static void virtscsi_complete_cmd(struct virtio_scsi *vscsi, void *buf) | |||
204 | set_driver_byte(sc, DRIVER_SENSE); | 199 | set_driver_byte(sc, DRIVER_SENSE); |
205 | } | 200 | } |
206 | 201 | ||
207 | mempool_free(cmd, virtscsi_cmd_pool); | ||
208 | sc->scsi_done(sc); | 202 | sc->scsi_done(sc); |
209 | 203 | ||
210 | atomic_dec(&tgt->reqs); | 204 | atomic_dec(&tgt->reqs); |
@@ -238,38 +232,6 @@ static void virtscsi_req_done(struct virtqueue *vq) | |||
238 | int index = vq->index - VIRTIO_SCSI_VQ_BASE; | 232 | int index = vq->index - VIRTIO_SCSI_VQ_BASE; |
239 | struct virtio_scsi_vq *req_vq = &vscsi->req_vqs[index]; | 233 | struct virtio_scsi_vq *req_vq = &vscsi->req_vqs[index]; |
240 | 234 | ||
241 | /* | ||
242 | * Read req_vq before decrementing the reqs field in | ||
243 | * virtscsi_complete_cmd. | ||
244 | * | ||
245 | * With barriers: | ||
246 | * | ||
247 | * CPU #0 virtscsi_queuecommand_multi (CPU #1) | ||
248 | * ------------------------------------------------------------ | ||
249 | * lock vq_lock | ||
250 | * read req_vq | ||
251 | * read reqs (reqs = 1) | ||
252 | * write reqs (reqs = 0) | ||
253 | * increment reqs (reqs = 1) | ||
254 | * write req_vq | ||
255 | * | ||
256 | * Possible reordering without barriers: | ||
257 | * | ||
258 | * CPU #0 virtscsi_queuecommand_multi (CPU #1) | ||
259 | * ------------------------------------------------------------ | ||
260 | * lock vq_lock | ||
261 | * read reqs (reqs = 1) | ||
262 | * write reqs (reqs = 0) | ||
263 | * increment reqs (reqs = 1) | ||
264 | * write req_vq | ||
265 | * read (wrong) req_vq | ||
266 | * | ||
267 | * We do not need a full smp_rmb, because req_vq is required to get | ||
268 | * to tgt->reqs: tgt is &vscsi->tgt[sc->device->id], where sc is stored | ||
269 | * in the virtqueue as the user token. | ||
270 | */ | ||
271 | smp_read_barrier_depends(); | ||
272 | |||
273 | virtscsi_vq_done(vscsi, req_vq, virtscsi_complete_cmd); | 235 | virtscsi_vq_done(vscsi, req_vq, virtscsi_complete_cmd); |
274 | }; | 236 | }; |
275 | 237 | ||
@@ -279,8 +241,6 @@ static void virtscsi_complete_free(struct virtio_scsi *vscsi, void *buf) | |||
279 | 241 | ||
280 | if (cmd->comp) | 242 | if (cmd->comp) |
281 | complete_all(cmd->comp); | 243 | complete_all(cmd->comp); |
282 | else | ||
283 | mempool_free(cmd, virtscsi_cmd_pool); | ||
284 | } | 244 | } |
285 | 245 | ||
286 | static void virtscsi_ctrl_done(struct virtqueue *vq) | 246 | static void virtscsi_ctrl_done(struct virtqueue *vq) |
@@ -496,10 +456,9 @@ static int virtscsi_queuecommand(struct virtio_scsi *vscsi, | |||
496 | struct virtio_scsi_vq *req_vq, | 456 | struct virtio_scsi_vq *req_vq, |
497 | struct scsi_cmnd *sc) | 457 | struct scsi_cmnd *sc) |
498 | { | 458 | { |
499 | struct virtio_scsi_cmd *cmd; | ||
500 | int ret; | ||
501 | |||
502 | struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev); | 459 | struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev); |
460 | struct virtio_scsi_cmd *cmd = scsi_cmd_priv(sc); | ||
461 | |||
503 | BUG_ON(scsi_sg_count(sc) > shost->sg_tablesize); | 462 | BUG_ON(scsi_sg_count(sc) > shost->sg_tablesize); |
504 | 463 | ||
505 | /* TODO: check feature bit and fail if unsupported? */ | 464 | /* TODO: check feature bit and fail if unsupported? */ |
@@ -508,11 +467,6 @@ static int virtscsi_queuecommand(struct virtio_scsi *vscsi, | |||
508 | dev_dbg(&sc->device->sdev_gendev, | 467 | dev_dbg(&sc->device->sdev_gendev, |
509 | "cmd %p CDB: %#02x\n", sc, sc->cmnd[0]); | 468 | "cmd %p CDB: %#02x\n", sc, sc->cmnd[0]); |
510 | 469 | ||
511 | ret = SCSI_MLQUEUE_HOST_BUSY; | ||
512 | cmd = mempool_alloc(virtscsi_cmd_pool, GFP_ATOMIC); | ||
513 | if (!cmd) | ||
514 | goto out; | ||
515 | |||
516 | memset(cmd, 0, sizeof(*cmd)); | 470 | memset(cmd, 0, sizeof(*cmd)); |
517 | cmd->sc = sc; | 471 | cmd->sc = sc; |
518 | cmd->req.cmd = (struct virtio_scsi_cmd_req){ | 472 | cmd->req.cmd = (struct virtio_scsi_cmd_req){ |
@@ -531,13 +485,9 @@ static int virtscsi_queuecommand(struct virtio_scsi *vscsi, | |||
531 | 485 | ||
532 | if (virtscsi_kick_cmd(req_vq, cmd, | 486 | if (virtscsi_kick_cmd(req_vq, cmd, |
533 | sizeof cmd->req.cmd, sizeof cmd->resp.cmd, | 487 | sizeof cmd->req.cmd, sizeof cmd->resp.cmd, |
534 | GFP_ATOMIC) == 0) | 488 | GFP_ATOMIC) != 0) |
535 | ret = 0; | 489 | return SCSI_MLQUEUE_HOST_BUSY; |
536 | else | 490 | return 0; |
537 | mempool_free(cmd, virtscsi_cmd_pool); | ||
538 | |||
539 | out: | ||
540 | return ret; | ||
541 | } | 491 | } |
542 | 492 | ||
543 | static int virtscsi_queuecommand_single(struct Scsi_Host *sh, | 493 | static int virtscsi_queuecommand_single(struct Scsi_Host *sh, |
@@ -560,12 +510,8 @@ static struct virtio_scsi_vq *virtscsi_pick_vq(struct virtio_scsi *vscsi, | |||
560 | 510 | ||
561 | spin_lock_irqsave(&tgt->tgt_lock, flags); | 511 | spin_lock_irqsave(&tgt->tgt_lock, flags); |
562 | 512 | ||
563 | /* | ||
564 | * The memory barrier after atomic_inc_return matches | ||
565 | * the smp_read_barrier_depends() in virtscsi_req_done. | ||
566 | */ | ||
567 | if (atomic_inc_return(&tgt->reqs) > 1) | 513 | if (atomic_inc_return(&tgt->reqs) > 1) |
568 | vq = ACCESS_ONCE(tgt->req_vq); | 514 | vq = tgt->req_vq; |
569 | else { | 515 | else { |
570 | queue_num = smp_processor_id(); | 516 | queue_num = smp_processor_id(); |
571 | while (unlikely(queue_num >= vscsi->num_queues)) | 517 | while (unlikely(queue_num >= vscsi->num_queues)) |
@@ -683,6 +629,7 @@ static struct scsi_host_template virtscsi_host_template_single = { | |||
683 | .name = "Virtio SCSI HBA", | 629 | .name = "Virtio SCSI HBA", |
684 | .proc_name = "virtio_scsi", | 630 | .proc_name = "virtio_scsi", |
685 | .this_id = -1, | 631 | .this_id = -1, |
632 | .cmd_size = sizeof(struct virtio_scsi_cmd), | ||
686 | .queuecommand = virtscsi_queuecommand_single, | 633 | .queuecommand = virtscsi_queuecommand_single, |
687 | .eh_abort_handler = virtscsi_abort, | 634 | .eh_abort_handler = virtscsi_abort, |
688 | .eh_device_reset_handler = virtscsi_device_reset, | 635 | .eh_device_reset_handler = virtscsi_device_reset, |
@@ -699,6 +646,7 @@ static struct scsi_host_template virtscsi_host_template_multi = { | |||
699 | .name = "Virtio SCSI HBA", | 646 | .name = "Virtio SCSI HBA", |
700 | .proc_name = "virtio_scsi", | 647 | .proc_name = "virtio_scsi", |
701 | .this_id = -1, | 648 | .this_id = -1, |
649 | .cmd_size = sizeof(struct virtio_scsi_cmd), | ||
702 | .queuecommand = virtscsi_queuecommand_multi, | 650 | .queuecommand = virtscsi_queuecommand_multi, |
703 | .eh_abort_handler = virtscsi_abort, | 651 | .eh_abort_handler = virtscsi_abort, |
704 | .eh_device_reset_handler = virtscsi_device_reset, | 652 | .eh_device_reset_handler = virtscsi_device_reset, |