Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

virtio-scsi: Implement change_queue_depth for virtscsi targets

change_queue_depth allows changing per-target queue depth via sysfs.

It also allows the SCSI midlayer to ramp down the number of concurrent
inflight requests in response to a SCSI BUSY status response and allows
the midlayer to ramp the count back up to the device maximum when the
BUSY condition has resolved.

Signed-off-by: Venkatesh Srinivas <venkateshs@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>

authored by

Venkatesh Srinivas and committed by
Christoph Hellwig
761f1193 938ece71

+33
+33
drivers/scsi/virtio_scsi.c
··· 27 27 #include <scsi/scsi_host.h> 28 28 #include <scsi/scsi_device.h> 29 29 #include <scsi/scsi_cmnd.h> 30 + #include <scsi/scsi_tcq.h> 30 31 #include <linux/seqlock.h> 31 32 32 33 #define VIRTIO_SCSI_MEMPOOL_SZ 64 ··· 655 654 return virtscsi_tmf(vscsi, cmd); 656 655 } 657 656 657 + /** 658 + * virtscsi_change_queue_depth() - Change a virtscsi target's queue depth 659 + * @sdev: Virtscsi target whose queue depth to change 660 + * @qdepth: New queue depth 661 + * @reason: Reason for the queue depth change. 662 + */ 663 + static int virtscsi_change_queue_depth(struct scsi_device *sdev, 664 + int qdepth, 665 + int reason) 666 + { 667 + struct Scsi_Host *shost = sdev->host; 668 + int max_depth = shost->cmd_per_lun; 669 + 670 + switch (reason) { 671 + case SCSI_QDEPTH_QFULL: /* Drop qdepth in response to BUSY state */ 672 + scsi_track_queue_full(sdev, qdepth); 673 + break; 674 + case SCSI_QDEPTH_RAMP_UP: /* Raise qdepth after BUSY state resolved */ 675 + case SCSI_QDEPTH_DEFAULT: /* Manual change via sysfs */ 676 + scsi_adjust_queue_depth(sdev, 677 + scsi_get_tag_type(sdev), 678 + min(max_depth, qdepth)); 679 + break; 680 + default: 681 + return -EOPNOTSUPP; 682 + } 683 + 684 + return sdev->queue_depth; 685 + } 686 + 658 687 static int virtscsi_abort(struct scsi_cmnd *sc) 659 688 { 660 689 struct virtio_scsi *vscsi = shost_priv(sc->device->host); ··· 740 709 .this_id = -1, 741 710 .cmd_size = sizeof(struct virtio_scsi_cmd), 742 711 .queuecommand = virtscsi_queuecommand_single, 712 + .change_queue_depth = virtscsi_change_queue_depth, 743 713 .eh_abort_handler = virtscsi_abort, 744 714 .eh_device_reset_handler = virtscsi_device_reset, 745 715 ··· 758 726 .this_id = -1, 759 727 .cmd_size = sizeof(struct virtio_scsi_cmd), 760 728 .queuecommand = virtscsi_queuecommand_multi, 729 + .change_queue_depth = virtscsi_change_queue_depth, 761 730 .eh_abort_handler = virtscsi_abort, 762 731 .eh_device_reset_handler = virtscsi_device_reset, 763 732