Merge tag 'char-misc-5.15-rc1-lkdtm' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / drivers / nvme / host / tcp.c
index 6450256..e2ab12f 100644 (file)
@@ -45,6 +45,7 @@ struct nvme_tcp_request {
        u32                     pdu_len;
        u32                     pdu_sent;
        u16                     ttag;
+       __le16                  status;
        struct list_head        entry;
        struct llist_node       lentry;
        __le32                  ddgst;
@@ -485,6 +486,7 @@ static void nvme_tcp_error_recovery(struct nvme_ctrl *ctrl)
 static int nvme_tcp_process_nvme_cqe(struct nvme_tcp_queue *queue,
                struct nvme_completion *cqe)
 {
+       struct nvme_tcp_request *req;
        struct request *rq;
 
        rq = nvme_find_rq(nvme_tcp_tagset(queue), cqe->command_id);
@@ -496,7 +498,11 @@ static int nvme_tcp_process_nvme_cqe(struct nvme_tcp_queue *queue,
                return -EINVAL;
        }
 
-       if (!nvme_try_complete_req(rq, cqe->status, cqe->result))
+       req = blk_mq_rq_to_pdu(rq);
+       if (req->status == cpu_to_le16(NVME_SC_SUCCESS))
+               req->status = cqe->status;
+
+       if (!nvme_try_complete_req(rq, req->status, cqe->result))
                nvme_complete_rq(rq);
        queue->nr_cqe++;
 
@@ -758,7 +764,8 @@ static int nvme_tcp_recv_data(struct nvme_tcp_queue *queue, struct sk_buff *skb,
                        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_end_request(rq,
+                                               le16_to_cpu(req->status));
                                queue->nr_cqe++;
                        }
                        nvme_tcp_init_recv_ctx(queue);
@@ -788,18 +795,24 @@ static int nvme_tcp_recv_ddgst(struct nvme_tcp_queue *queue,
                return 0;
 
        if (queue->recv_ddgst != queue->exp_ddgst) {
+               struct request *rq = nvme_cid_to_rq(nvme_tcp_tagset(queue),
+                                       pdu->command_id);
+               struct nvme_tcp_request *req = blk_mq_rq_to_pdu(rq);
+
+               req->status = cpu_to_le16(NVME_SC_DATA_XFER_ERROR);
+
                dev_err(queue->ctrl->ctrl.device,
                        "data digest error: recv %#x expected %#x\n",
                        le32_to_cpu(queue->recv_ddgst),
                        le32_to_cpu(queue->exp_ddgst));
-               return -EIO;
        }
 
        if (pdu->hdr.flags & NVME_TCP_F_DATA_SUCCESS) {
                struct request *rq = nvme_cid_to_rq(nvme_tcp_tagset(queue),
                                        pdu->command_id);
+               struct nvme_tcp_request *req = blk_mq_rq_to_pdu(rq);
 
-               nvme_tcp_end_request(rq, NVME_SC_SUCCESS);
+               nvme_tcp_end_request(rq, le16_to_cpu(req->status));
                queue->nr_cqe++;
        }
 
@@ -2293,6 +2306,7 @@ static blk_status_t nvme_tcp_setup_cmd_pdu(struct nvme_ns *ns,
                return ret;
 
        req->state = NVME_TCP_SEND_CMD_PDU;
+       req->status = cpu_to_le16(NVME_SC_SUCCESS);
        req->offset = 0;
        req->data_sent = 0;
        req->pdu_len = 0;