NVMe: Fix endian-related problems in user I/O submission path
When constructing the command, dsmgmt needs to be treated as a 32-bit
value, not a 16-bit value. reftag, apptag and appmask all need to be
converted from native-endian to little-endian. Again, sparse's bitwise
warnings caught this problem. Thanks to Keith for pointing out the
correct way to fix the reftag.
Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
Acked-by: Keith Busch <keith.busch@intel.com>
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index a3c7d50..dbd2103 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -1166,10 +1166,10 @@
c.rw.slba = cpu_to_le64(io.slba);
c.rw.length = cpu_to_le16(io.nblocks);
c.rw.control = cpu_to_le16(io.control);
- c.rw.dsmgmt = cpu_to_le16(io.dsmgmt);
- c.rw.reftag = io.reftag;
- c.rw.apptag = io.apptag;
- c.rw.appmask = io.appmask;
+ c.rw.dsmgmt = cpu_to_le32(io.dsmgmt);
+ c.rw.reftag = cpu_to_le32(io.reftag);
+ c.rw.apptag = cpu_to_le16(io.apptag);
+ c.rw.appmask = cpu_to_le16(io.appmask);
/* XXX: metadata */
length = nvme_setup_prps(dev, &c.common, iod, length, GFP_KERNEL);
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index 09f419d..7ae7ecf 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -207,11 +207,11 @@
__u8 flags;
__u16 command_id;
__le32 nsid;
- __u32 cdw2[2];
+ __le32 cdw2[2];
__le64 metadata;
__le64 prp1;
__le64 prp2;
- __u32 cdw10[6];
+ __le32 cdw10[6];
};
struct nvme_rw_command {