aboutsummaryrefslogtreecommitdiff
path: root/pc-bios/s390-ccw/virtio-scsi.c
diff options
context:
space:
mode:
authorEric Farman <farman@linux.vnet.ibm.com>2017-05-10 17:53:57 +0200
committerCornelia Huck <cornelia.huck@de.ibm.com>2017-05-19 12:29:01 +0200
commitfe921fc8b7e92020bb140079a9f47f14fb8e9075 (patch)
treeb40bd42284828ff0b2908e692369d2f0e84ce29c /pc-bios/s390-ccw/virtio-scsi.c
parent8edfe85bef669d676ad17cd84b4e3dce43b110e4 (diff)
downloadqemu-fe921fc8b7e92020bb140079a9f47f14fb8e9075.zip
qemu-fe921fc8b7e92020bb140079a9f47f14fb8e9075.tar.gz
qemu-fe921fc8b7e92020bb140079a9f47f14fb8e9075.tar.bz2
pc-bios/s390-ccw: Get Block Limits VPD device data
The "Block Limits" Inquiry VPD page is optional for any SCSI device, but if it's supported it provides a hint of the maximum I/O transfer length for this particular device. If this page is supported by the disk, let's issue that Inquiry and use the minimum of it and the SCSI controller limit. That will cover this scenario: qemu-system-s390x ... -device virtio-scsi-ccw,id=scsi0,max_sectors=32768 ... -drive file=/dev/sda,if=none,id=drive0,format=raw ... -device scsi-hd,bus=scsi0.0,channel=0,scsi-id=0, drive=drive0,id=disk0,max_io_size=1048576 controller: 32768 sectors x 512 bytes/sector = 16777216 bytes disk: 1048576 bytes Now that we have a limit for a virtio-scsi disk, compare that with the limit for the virtio-scsi controller when we actually build the I/O. The minimum of these two limits should be the one we use. Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> Message-Id: <20170510155359.32727-7-farman@linux.vnet.ibm.com> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Diffstat (limited to 'pc-bios/s390-ccw/virtio-scsi.c')
-rw-r--r--pc-bios/s390-ccw/virtio-scsi.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/pc-bios/s390-ccw/virtio-scsi.c b/pc-bios/s390-ccw/virtio-scsi.c
index e34755c..b722f25 100644
--- a/pc-bios/s390-ccw/virtio-scsi.c
+++ b/pc-bios/s390-ccw/virtio-scsi.c
@@ -20,6 +20,7 @@ static VirtioScsiCmdResp resp;
static uint8_t scsi_inquiry_std_response[256];
static ScsiInquiryEvpdPages scsi_inquiry_evpd_pages_response;
+static ScsiInquiryEvpdBl scsi_inquiry_evpd_bl_response;
static inline void vs_assert(bool term, const char **msgs)
{
@@ -262,9 +263,11 @@ int virtio_scsi_read_many(VDev *vdev,
int sector_count;
int f = vdev->blk_factor;
unsigned int data_size;
+ unsigned int max_transfer = MIN_NON_ZERO(vdev->config.scsi.max_sectors,
+ vdev->max_transfer);
do {
- sector_count = MIN_NON_ZERO(sec_num, vdev->config.scsi.max_sectors);
+ sector_count = MIN_NON_ZERO(sec_num, max_transfer);
data_size = sector_count * virtio_get_block_size() * f;
if (!scsi_read_10(vdev, sector * f, sector_count * f, load_addr,
data_size)) {
@@ -321,6 +324,7 @@ void virtio_scsi_setup(VDev *vdev)
uint8_t data[256];
uint32_t data_size = sizeof(data);
ScsiInquiryEvpdPages *evpd = &scsi_inquiry_evpd_pages_response;
+ ScsiInquiryEvpdBl *evpd_bl = &scsi_inquiry_evpd_bl_response;
int i;
vdev->scsi_device = &default_scsi_device;
@@ -378,6 +382,21 @@ void virtio_scsi_setup(VDev *vdev)
for (i = 0; i <= evpd->page_length; i++) {
debug_print_int("supported EVPD page", evpd->byte[i]);
+
+ if (evpd->byte[i] != SCSI_INQUIRY_EVPD_BLOCK_LIMITS) {
+ continue;
+ }
+
+ if (!scsi_inquiry(vdev,
+ SCSI_INQUIRY_EVPD,
+ SCSI_INQUIRY_EVPD_BLOCK_LIMITS,
+ evpd_bl,
+ sizeof(*evpd_bl))) {
+ virtio_scsi_verify_response(&resp, "virtio-scsi:setup:blocklimits");
+ }
+
+ debug_print_int("max transfer", evpd_bl->max_transfer);
+ vdev->max_transfer = evpd_bl->max_transfer;
}
if (!scsi_read_capacity(vdev, data, data_size)) {