aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/virtio_scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/virtio_scsi.c')
-rw-r--r--drivers/scsi/virtio_scsi.c78
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
286static void virtscsi_ctrl_done(struct virtqueue *vq) 246static 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
539out:
540 return ret;
541} 491}
542 492
543static int virtscsi_queuecommand_single(struct Scsi_Host *sh, 493static 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,