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:54 +0200
committerCornelia Huck <cornelia.huck@de.ibm.com>2017-05-19 12:29:01 +0200
commit5ffd4a3c2d75db3ed31752d0936f96719ee0257b (patch)
tree5f640f88de5eaad9a03950f5535a48b88421fa28 /pc-bios/s390-ccw/virtio-scsi.c
parent98d3c524359fda04337c8369b617f2d5ef37bf5f (diff)
pc-bios/s390-ccw: Break up virtio-scsi read into multiples
A virtio-scsi request that goes through the host sd driver and exceeds the maximum transfer size is automatically broken up for us. But the equivalent request going to the sg driver presumes that any length requirements have already been honored. Let's use the max_sectors field on the virtio-scsi controller device, and break up all requests (both sd and sg) to avoid this problem. Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> Message-Id: <20170510155359.32727-4-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.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/pc-bios/s390-ccw/virtio-scsi.c b/pc-bios/s390-ccw/virtio-scsi.c
index 6d070e2f73..ff65e2ee30 100644
--- a/pc-bios/s390-ccw/virtio-scsi.c
+++ b/pc-bios/s390-ccw/virtio-scsi.c
@@ -202,6 +202,7 @@ static void virtio_scsi_locate_device(VDev *vdev)
debug_print_int("config.scsi.max_channel", vdev->config.scsi.max_channel);
debug_print_int("config.scsi.max_target ", vdev->config.scsi.max_target);
debug_print_int("config.scsi.max_lun ", vdev->config.scsi.max_lun);
+ debug_print_int("config.scsi.max_sectors", vdev->config.scsi.max_sectors);
if (vdev->scsi_device_selected) {
sdev->channel = vdev->selected_scsi_device.channel;
@@ -254,12 +255,21 @@ static void virtio_scsi_locate_device(VDev *vdev)
int virtio_scsi_read_many(VDev *vdev,
ulong sector, void *load_addr, int sec_num)
{
+ int sector_count;
int f = vdev->blk_factor;
- unsigned int data_size = sec_num * virtio_get_block_size() * f;
-
- if (!scsi_read_10(vdev, sector * f, sec_num * f, load_addr, data_size)) {
- virtio_scsi_verify_response(&resp, "virtio-scsi:read_many");
- }
+ unsigned int data_size;
+
+ do {
+ sector_count = MIN_NON_ZERO(sec_num, vdev->config.scsi.max_sectors);
+ data_size = sector_count * virtio_get_block_size() * f;
+ if (!scsi_read_10(vdev, sector * f, sector_count * f, load_addr,
+ data_size)) {
+ virtio_scsi_verify_response(&resp, "virtio-scsi:read_many");
+ }
+ load_addr += data_size;
+ sector += sector_count;
+ sec_num -= sector_count;
+ } while (sec_num > 0);
return 0;
}