diff options
author | Matias Bjorling <m@bjorling.me> | 2016-03-03 09:06:39 -0500 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2016-03-18 21:10:38 -0400 |
commit | 9f867268436d799549909437e627e7cf279e1127 (patch) | |
tree | 8ebc862034aec40f4ecc59d65ea31ef3787cf27f | |
parent | da1e284919b0b99c5bf0618b6c98cbaf2c17e62e (diff) |
nvme: lightnvm: return ppa completion status
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>
-rw-r--r-- | drivers/nvme/host/lightnvm.c | 17 | ||||
-rw-r--r-- | include/linux/lightnvm.h | 1 |
2 files changed, 16 insertions, 2 deletions
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c index 42a01a931989..9461dd639acd 100644 --- a/drivers/nvme/host/lightnvm.c +++ b/drivers/nvme/host/lightnvm.c | |||
@@ -146,6 +146,14 @@ struct nvme_nvm_command { | |||
146 | }; | 146 | }; |
147 | }; | 147 | }; |
148 | 148 | ||
149 | struct nvme_nvm_completion { | ||
150 | __le64 result; /* Used by LightNVM to return ppa completions */ | ||
151 | __le16 sq_head; /* how much of this queue may be reclaimed */ | ||
152 | __le16 sq_id; /* submission queue that generated this entry */ | ||
153 | __u16 command_id; /* of the command which completed */ | ||
154 | __le16 status; /* did the command fail, and if so, why? */ | ||
155 | }; | ||
156 | |||
149 | #define NVME_NVM_LP_MLC_PAIRS 886 | 157 | #define NVME_NVM_LP_MLC_PAIRS 886 |
150 | struct nvme_nvm_lp_mlc { | 158 | struct nvme_nvm_lp_mlc { |
151 | __u16 num_pairs; | 159 | __u16 num_pairs; |
@@ -507,6 +515,10 @@ static inline void nvme_nvm_rqtocmd(struct request *rq, struct nvm_rq *rqd, | |||
507 | static void nvme_nvm_end_io(struct request *rq, int error) | 515 | static void nvme_nvm_end_io(struct request *rq, int error) |
508 | { | 516 | { |
509 | struct nvm_rq *rqd = rq->end_io_data; | 517 | struct nvm_rq *rqd = rq->end_io_data; |
518 | struct nvme_nvm_completion *cqe = rq->special; | ||
519 | |||
520 | if (cqe) | ||
521 | rqd->ppa_status = le64_to_cpu(cqe->result); | ||
510 | 522 | ||
511 | nvm_end_io(rqd, error); | 523 | nvm_end_io(rqd, error); |
512 | 524 | ||
@@ -526,7 +538,8 @@ static int nvme_nvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd) | |||
526 | if (IS_ERR(rq)) | 538 | if (IS_ERR(rq)) |
527 | return -ENOMEM; | 539 | return -ENOMEM; |
528 | 540 | ||
529 | cmd = kzalloc(sizeof(struct nvme_nvm_command), GFP_KERNEL); | 541 | cmd = kzalloc(sizeof(struct nvme_nvm_command) + |
542 | sizeof(struct nvme_nvm_completion), GFP_KERNEL); | ||
530 | if (!cmd) { | 543 | if (!cmd) { |
531 | blk_mq_free_request(rq); | 544 | blk_mq_free_request(rq); |
532 | return -ENOMEM; | 545 | return -ENOMEM; |
@@ -545,7 +558,7 @@ static int nvme_nvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd) | |||
545 | 558 | ||
546 | rq->cmd = (unsigned char *)cmd; | 559 | rq->cmd = (unsigned char *)cmd; |
547 | rq->cmd_len = sizeof(struct nvme_nvm_command); | 560 | rq->cmd_len = sizeof(struct nvme_nvm_command); |
548 | rq->special = (void *)0; | 561 | rq->special = cmd + 1; |
549 | 562 | ||
550 | rq->end_io_data = rqd; | 563 | rq->end_io_data = rqd; |
551 | 564 | ||
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index 0ee2c2c78ffd..cdcb2ccbefa8 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h | |||
@@ -242,6 +242,7 @@ struct nvm_rq { | |||
242 | uint16_t nr_pages; | 242 | uint16_t nr_pages; |
243 | uint16_t flags; | 243 | uint16_t flags; |
244 | 244 | ||
245 | u64 ppa_status; /* ppa media status */ | ||
245 | int error; | 246 | int error; |
246 | }; | 247 | }; |
247 | 248 | ||