From 19cd2b3ccc5e78ea33fb1d1ceef6db69117f044b Mon Sep 17 00:00:00 2001 From: Sanjith T D Date: Wed, 26 Apr 2023 05:40:51 +0000 Subject: [PATCH] vblk: Handle SCSI IOCTL case where mx_sb_len is 0 Storage server expectes the mx_sb_len to be set to non-zero value in order to pass on the sense information assosiated with the SCSI command to the user. Some of the open source implementations(Ex:f2fs) that use SG_IO SCSI IOCTL interface set the mx_sb_len to 0. Handle this case in the vblk client driver. Bug 4060482 Change-Id: Ib3779f9cd4beb2822add95d4773909b7d3e7217a Signed-off-by: Sanjith T D Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2894395 Reviewed-by: svcacv Reviewed-by: Manish Bhardwaj Reviewed-by: svc-mobile-coverity Reviewed-by: svc-mobile-cert Reviewed-by: Vipin Kumar GVS: Gerrit_Virtual_Submit --- .../block/tegra_virt_storage/tegra_hv_scsi.c | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/block/tegra_virt_storage/tegra_hv_scsi.c b/drivers/block/tegra_virt_storage/tegra_hv_scsi.c index 13adaf68..48d87813 100644 --- a/drivers/block/tegra_virt_storage/tegra_hv_scsi.c +++ b/drivers/block/tegra_virt_storage/tegra_hv_scsi.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ #include @@ -16,6 +16,8 @@ #include #include "tegra_vblk.h" +#define UFS_REQUEST_SENS_DATA_LEN 18U + int vblk_prep_sg_io(struct vblk_dev *vblkdev, struct vblk_ioctl_req *ioctl_req, void __user *user) @@ -35,6 +37,7 @@ int vblk_prep_sg_io(struct vblk_dev *vblkdev, uint32_t data_buf_size_aligned; uint32_t ioctl_len; void *ioctl_buf = NULL; + uint32_t max_sb_len; hp = kmalloc(header_len, GFP_KERNEL); if (hp == NULL) { @@ -59,8 +62,13 @@ int vblk_prep_sg_io(struct vblk_dev *vblkdev, err = - EMSGSIZE; goto free_hp; } + if (hp->mx_sb_len == 0) + max_sb_len = UFS_REQUEST_SENS_DATA_LEN; + else + max_sb_len = hp->mx_sb_len; + + data_buf_offset = (sbp_offset + max_sb_len); - data_buf_offset = (sbp_offset + hp->mx_sb_len); if (data_buf_offset < sbp_offset) { err = -EMSGSIZE; goto free_hp; @@ -129,7 +137,7 @@ int vblk_prep_sg_io(struct vblk_dev *vblkdev, } vblk_hp->cmd_len = hp->cmd_len; - vblk_hp->mx_sb_len = hp->mx_sb_len; + vblk_hp->mx_sb_len = max_sb_len; /* This is actual data len on which storage server needs to act */ vblk_hp->dxfer_len = hp->dxfer_len; /* This is the data buffer len, data length is strictly dependent on the @@ -191,7 +199,11 @@ int vblk_complete_sg_io(struct vblk_dev *vblkdev, hp->masked_status = status_byte(vblk_hp->status); hp->host_status = host_byte(vblk_hp->status); hp->driver_status = driver_byte(vblk_hp->status); - hp->sb_len_wr = vblk_hp->sb_len_wr; + if (hp->mx_sb_len != 0U) + hp->sb_len_wr = vblk_hp->sb_len_wr; + else + hp->sb_len_wr = 0U; + /* TODO: Handle the residual length */ hp->resid = 0;