#define CMPLT_HDR_ERROR_PHASE_MSK   (0xff << CMPLT_HDR_ERROR_PHASE_OFF)
 #define CMPLT_HDR_RSPNS_XFRD_OFF       10
 #define CMPLT_HDR_RSPNS_XFRD_MSK       (0x1 << CMPLT_HDR_RSPNS_XFRD_OFF)
+#define CMPLT_HDR_RSPNS_GOOD_OFF       11
+#define CMPLT_HDR_RSPNS_GOOD_MSK       (0x1 << CMPLT_HDR_RSPNS_GOOD_OFF)
 #define CMPLT_HDR_ERX_OFF              12
 #define CMPLT_HDR_ERX_MSK              (0x1 << CMPLT_HDR_ERX_OFF)
 #define CMPLT_HDR_ABORT_STAT_OFF       13
        return IRQ_HANDLED;
 }
 
-static void
+static bool
 slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
               struct hisi_sas_slot *slot)
 {
        switch (task->task_proto) {
        case SAS_PROTOCOL_SSP:
                if (dma_rx_err_type & RX_DATA_LEN_UNDERFLOW_MSK) {
+                       /*
+                        * If returned response frame is incorrect because of data underflow,
+                        * but I/O information has been written to the host memory, we examine
+                        * response IU.
+                        */
+                       if (!(complete_hdr->dw0 & CMPLT_HDR_RSPNS_GOOD_MSK) &&
+                               (complete_hdr->dw0 & CMPLT_HDR_RSPNS_XFRD_MSK))
+                               return false;
+
                        ts->residual = trans_tx_fail_type;
                        ts->stat = SAS_DATA_UNDERRUN;
                } else if (dw3 & CMPLT_HDR_IO_IN_TARGET_MSK) {
        default:
                break;
        }
+       return true;
 }
 
 static void slot_complete_v3_hw(struct hisi_hba *hisi_hba,
        if ((dw0 & CMPLT_HDR_CMPLT_MSK) == 0x3) {
                u32 *error_info = hisi_sas_status_buf_addr_mem(slot);
 
-               slot_err_v3_hw(hisi_hba, task, slot);
-               if (ts->stat != SAS_DATA_UNDERRUN)
-                       dev_info(dev, "erroneous completion iptt=%d task=%pK dev id=%d addr=%016llx CQ hdr: 0x%x 0x%x 0x%x 0x%x Error info: 0x%x 0x%x 0x%x 0x%x\n",
-                                slot->idx, task, sas_dev->device_id,
-                                SAS_ADDR(device->sas_addr),
-                                dw0, dw1, complete_hdr->act, dw3,
-                                error_info[0], error_info[1],
-                                error_info[2], error_info[3]);
-               if (unlikely(slot->abort)) {
-                       sas_task_abort(task);
-                       return;
+               if (slot_err_v3_hw(hisi_hba, task, slot)) {
+                       if (ts->stat != SAS_DATA_UNDERRUN)
+                               dev_info(dev, "erroneous completion iptt=%d task=%pK dev id=%d addr=%016llx CQ hdr: 0x%x 0x%x 0x%x 0x%x Error info: 0x%x 0x%x 0x%x 0x%x\n",
+                                       slot->idx, task, sas_dev->device_id,
+                                       SAS_ADDR(device->sas_addr),
+                                       dw0, dw1, complete_hdr->act, dw3,
+                                       error_info[0], error_info[1],
+                                       error_info[2], error_info[3]);
+                       if (unlikely(slot->abort)) {
+                               sas_task_abort(task);
+                               return;
+                       }
+                       goto out;
                }
-               goto out;
        }
 
        switch (task->task_proto) {