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 <std@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2894395
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Manish Bhardwaj <mbhardwaj@nvidia.com>
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: svc-mobile-cert <svc-mobile-cert@nvidia.com>
Reviewed-by: Vipin Kumar <vipink@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
Sanjith T D
2023-04-26 05:40:51 +00:00
committed by mobile promotions
parent 5395e466bf
commit 19cd2b3ccc

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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 <linux/module.h> #include <linux/module.h>
@@ -16,6 +16,8 @@
#include <scsi/sg.h> #include <scsi/sg.h>
#include "tegra_vblk.h" #include "tegra_vblk.h"
#define UFS_REQUEST_SENS_DATA_LEN 18U
int vblk_prep_sg_io(struct vblk_dev *vblkdev, int vblk_prep_sg_io(struct vblk_dev *vblkdev,
struct vblk_ioctl_req *ioctl_req, struct vblk_ioctl_req *ioctl_req,
void __user *user) void __user *user)
@@ -35,6 +37,7 @@ int vblk_prep_sg_io(struct vblk_dev *vblkdev,
uint32_t data_buf_size_aligned; uint32_t data_buf_size_aligned;
uint32_t ioctl_len; uint32_t ioctl_len;
void *ioctl_buf = NULL; void *ioctl_buf = NULL;
uint32_t max_sb_len;
hp = kmalloc(header_len, GFP_KERNEL); hp = kmalloc(header_len, GFP_KERNEL);
if (hp == NULL) { if (hp == NULL) {
@@ -59,8 +62,13 @@ int vblk_prep_sg_io(struct vblk_dev *vblkdev,
err = - EMSGSIZE; err = - EMSGSIZE;
goto free_hp; 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) { if (data_buf_offset < sbp_offset) {
err = -EMSGSIZE; err = -EMSGSIZE;
goto free_hp; 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->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 */ /* This is actual data len on which storage server needs to act */
vblk_hp->dxfer_len = hp->dxfer_len; vblk_hp->dxfer_len = hp->dxfer_len;
/* This is the data buffer len, data length is strictly dependent on the /* 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->masked_status = status_byte(vblk_hp->status);
hp->host_status = host_byte(vblk_hp->status); hp->host_status = host_byte(vblk_hp->status);
hp->driver_status = driver_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 */ /* TODO: Handle the residual length */
hp->resid = 0; hp->resid = 0;