@@ -984,6 +984,7 @@ static inline blk_status_t nvme_setup_rw(struct nvme_ns *ns,
{
u16 control = 0;
u32 dsmgmt = 0;
+ u8 type;
if (req->cmd_flags & REQ_FUA)
control |= NVME_RW_FUA;
@@ -1022,7 +1023,21 @@ static inline blk_status_t nvme_setup_rw(struct nvme_ns *ns,
return BLK_STS_NOTSUPP;
control |= NVME_RW_PRINFO_PRACT;
}
+ if (req->cmd_flags & REQ_INTEGRITY_OFFLOAD) {
+ type = ns->head->pi_offload_type;
+ if (type == BLK_INTEGRITY_OFFLOAD_NONE ||
+ (type == BLK_INTEGRITY_OFFLOAD_BUF &&
+ !blk_integrity_rq(req))) {
+ WARN_ON_ONCE(1);
+ return BLK_STS_NOTSUPP;
+ }
+
+ control |= NVME_RW_PRINFO_PRACT |
+ NVME_RW_PRINFO_PRCHK_GUARD;
+ /* skip redundant processing for offload */
+ goto out;
+ }
if (bio_integrity_flagged(req->bio, BIP_CHECK_GUARD))
control |= NVME_RW_PRINFO_PRCHK_GUARD;
if (bio_integrity_flagged(req->bio, BIP_CHECK_REFTAG)) {
@@ -1037,6 +1052,7 @@ static inline blk_status_t nvme_setup_rw(struct nvme_ns *ns,
}
}
+out:
cmnd->rw.control = cpu_to_le16(control);
cmnd->rw.dsmgmt = cpu_to_le32(dsmgmt);
return 0;
@@ -1846,6 +1862,14 @@ static bool nvme_init_integrity(struct nvme_ns_head *head,
bi->tuple_size = head->ms;
bi->pi_offset = info->pi_offset;
+ if (bi->csum_type != BLK_INTEGRITY_CSUM_NONE) {
+ if (head->ms == head->pi_size)
+ bi->offload_type = BLK_INTEGRITY_OFFLOAD_NO_BUF;
+ else
+ bi->offload_type = BLK_INTEGRITY_OFFLOAD_BUF;
+ head->pi_offload_type = bi->offload_type;
+ }
+
return true;
}
@@ -476,6 +476,7 @@ struct nvme_ns_head {
u16 pi_size;
u8 pi_type;
u8 guard_type;
+ u8 pi_offload_type;
struct list_head entry;
struct kref ref;
bool shared;
Register the integrity offload with the block layer if it is supported by the device. Serve incoming offload requests by setting PRACT and GUARD check. Signed-off-by: Kanchan Joshi <joshi.k@samsung.com> --- drivers/nvme/host/core.c | 24 ++++++++++++++++++++++++ drivers/nvme/host/nvme.h | 1 + 2 files changed, 25 insertions(+)