queue->data_remaining = le32_to_cpu(pdu->data_length);
 
+       if (pdu->hdr.flags & NVME_TCP_F_DATA_SUCCESS &&
+           unlikely(!(pdu->hdr.flags & NVME_TCP_F_DATA_LAST))) {
+               dev_err(queue->ctrl->ctrl.device,
+                       "queue %d tag %#x SUCCESS set but not last PDU\n",
+                       nvme_tcp_queue_id(queue), rq->tag);
+               nvme_tcp_error_recovery(&queue->ctrl->ctrl);
+               return -EPROTO;
+       }
+
        return 0;
 
 }
        return ret;
 }
 
+static inline void nvme_tcp_end_request(struct request *rq, __le16 status)
+{
+       union nvme_result res = {};
+
+       nvme_end_request(rq, cpu_to_le16(status << 1), res);
+}
+
+
 static int nvme_tcp_recv_data(struct nvme_tcp_queue *queue, struct sk_buff *skb,
                              unsigned int *offset, size_t *len)
 {
                        nvme_tcp_ddgst_final(queue->rcv_hash, &queue->exp_ddgst);
                        queue->ddgst_remaining = NVME_TCP_DIGEST_LENGTH;
                } else {
+                       if (pdu->hdr.flags & NVME_TCP_F_DATA_SUCCESS)
+                               nvme_tcp_end_request(rq, NVME_SC_SUCCESS);
                        nvme_tcp_init_recv_ctx(queue);
                }
        }
 static int nvme_tcp_recv_ddgst(struct nvme_tcp_queue *queue,
                struct sk_buff *skb, unsigned int *offset, size_t *len)
 {
+       struct nvme_tcp_data_pdu *pdu = (void *)queue->pdu;
        char *ddgst = (char *)&queue->recv_ddgst;
        size_t recv_len = min_t(size_t, *len, queue->ddgst_remaining);
        off_t off = NVME_TCP_DIGEST_LENGTH - queue->ddgst_remaining;
                return -EIO;
        }
 
+       if (pdu->hdr.flags & NVME_TCP_F_DATA_SUCCESS) {
+               struct request *rq = blk_mq_tag_to_rq(nvme_tcp_tagset(queue),
+                                               pdu->command_id);
+
+               nvme_tcp_end_request(rq, NVME_SC_SUCCESS);
+       }
+
        nvme_tcp_init_recv_ctx(queue);
        return 0;
 }
 
 static void nvme_tcp_fail_request(struct nvme_tcp_request *req)
 {
-       union nvme_result res = {};
-
-       nvme_end_request(blk_mq_rq_from_pdu(req),
-               cpu_to_le16(NVME_SC_DATA_XFER_ERROR), res);
+       nvme_tcp_end_request(blk_mq_rq_from_pdu(req), NVME_SC_DATA_XFER_ERROR);
 }
 
 static int nvme_tcp_try_send_data(struct nvme_tcp_request *req)