RDMA/srpt: Report the SCSI residual to the initiator
authorBart Van Assche <bvanassche@acm.org>
Tue, 5 Nov 2019 21:46:32 +0000 (13:46 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 23 Jan 2020 07:19:35 +0000 (08:19 +0100)
commit e88982ad1bb12db699de96fbc07096359ef6176c upstream.

The code added by this patch is similar to the code that already exists in
ibmvscsis_determine_resid(). This patch has been tested by running the
following command:

strace sg_raw -r 1k /dev/sdb 12 00 00 00 60 00 -o inquiry.bin |&
    grep resid=

Link: https://lore.kernel.org/r/20191105214632.183302-1-bvanassche@acm.org
Fixes: a42d985bd5b2 ("ib_srpt: Initial SRP Target merge for v3.3-rc1")
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Acked-by: Honggang Li <honli@redhat.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/infiniband/ulp/srpt/ib_srpt.c

index 6914cc18b4a1e585c9266decd7690c30dfc6027c..8acf337c3691d8c26de3fc4af7abee684b821fc8 100644 (file)
@@ -1234,9 +1234,11 @@ static int srpt_build_cmd_rsp(struct srpt_rdma_ch *ch,
                              struct srpt_send_ioctx *ioctx, u64 tag,
                              int status)
 {
+       struct se_cmd *cmd = &ioctx->cmd;
        struct srp_rsp *srp_rsp;
        const u8 *sense_data;
        int sense_data_len, max_sense_len;
+       u32 resid = cmd->residual_count;
 
        /*
         * The lowest bit of all SAM-3 status codes is zero (see also
@@ -1258,6 +1260,28 @@ static int srpt_build_cmd_rsp(struct srpt_rdma_ch *ch,
        srp_rsp->tag = tag;
        srp_rsp->status = status;
 
+       if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) {
+               if (cmd->data_direction == DMA_TO_DEVICE) {
+                       /* residual data from an underflow write */
+                       srp_rsp->flags = SRP_RSP_FLAG_DOUNDER;
+                       srp_rsp->data_out_res_cnt = cpu_to_be32(resid);
+               } else if (cmd->data_direction == DMA_FROM_DEVICE) {
+                       /* residual data from an underflow read */
+                       srp_rsp->flags = SRP_RSP_FLAG_DIUNDER;
+                       srp_rsp->data_in_res_cnt = cpu_to_be32(resid);
+               }
+       } else if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT) {
+               if (cmd->data_direction == DMA_TO_DEVICE) {
+                       /* residual data from an overflow write */
+                       srp_rsp->flags = SRP_RSP_FLAG_DOOVER;
+                       srp_rsp->data_out_res_cnt = cpu_to_be32(resid);
+               } else if (cmd->data_direction == DMA_FROM_DEVICE) {
+                       /* residual data from an overflow read */
+                       srp_rsp->flags = SRP_RSP_FLAG_DIOVER;
+                       srp_rsp->data_in_res_cnt = cpu_to_be32(resid);
+               }
+       }
+
        if (sense_data_len) {
                BUILD_BUG_ON(MIN_MAX_RSP_SIZE <= sizeof(*srp_rsp));
                max_sense_len = ch->max_ti_iu_len - sizeof(*srp_rsp);