nvme: lightnvm: return ppa completion status
authorMatias Bjorling <m@bjorling.me>
Thu, 3 Mar 2016 14:06:39 +0000 (15:06 +0100)
committerJens Axboe <axboe@fb.com>
Sat, 19 Mar 2016 01:10:38 +0000 (18:10 -0700)
PPAs sent to device is separately acknowledge in a 64bit status
variable. The status is stored in DW0 and DW1 of the completion queue
entry. Store this status inside the nvm_rq for further processing.

This can later be used to implement retry techniques for failed writes
and reads.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Matias Bjørling <m@bjorling.me>
Signed-off-by: Jens Axboe <axboe@fb.com>
drivers/nvme/host/lightnvm.c
include/linux/lightnvm.h

index 42a01a9..9461dd6 100644 (file)
@@ -146,6 +146,14 @@ struct nvme_nvm_command {
        };
 };
 
+struct nvme_nvm_completion {
+       __le64  result;         /* Used by LightNVM to return ppa completions */
+       __le16  sq_head;        /* how much of this queue may be reclaimed */
+       __le16  sq_id;          /* submission queue that generated this entry */
+       __u16   command_id;     /* of the command which completed */
+       __le16  status;         /* did the command fail, and if so, why? */
+};
+
 #define NVME_NVM_LP_MLC_PAIRS 886
 struct nvme_nvm_lp_mlc {
        __u16                   num_pairs;
@@ -507,6 +515,10 @@ static inline void nvme_nvm_rqtocmd(struct request *rq, struct nvm_rq *rqd,
 static void nvme_nvm_end_io(struct request *rq, int error)
 {
        struct nvm_rq *rqd = rq->end_io_data;
+       struct nvme_nvm_completion *cqe = rq->special;
+
+       if (cqe)
+               rqd->ppa_status = le64_to_cpu(cqe->result);
 
        nvm_end_io(rqd, error);
 
@@ -526,7 +538,8 @@ static int nvme_nvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)
        if (IS_ERR(rq))
                return -ENOMEM;
 
-       cmd = kzalloc(sizeof(struct nvme_nvm_command), GFP_KERNEL);
+       cmd = kzalloc(sizeof(struct nvme_nvm_command) +
+                               sizeof(struct nvme_nvm_completion), GFP_KERNEL);
        if (!cmd) {
                blk_mq_free_request(rq);
                return -ENOMEM;
@@ -545,7 +558,7 @@ static int nvme_nvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)
 
        rq->cmd = (unsigned char *)cmd;
        rq->cmd_len = sizeof(struct nvme_nvm_command);
-       rq->special = (void *)0;
+       rq->special = cmd + 1;
 
        rq->end_io_data = rqd;
 
index 0ee2c2c..cdcb2cc 100644 (file)
@@ -242,6 +242,7 @@ struct nvm_rq {
        uint16_t nr_pages;
        uint16_t flags;
 
+       u64 ppa_status; /* ppa media status */
        int error;
 };