From: Denis Mukhin <[email protected]> Enable FUA (if present) on NVMe devices to prevent any potential data integrity issues caused by accidental power loss or malformed device handoff sequence to the OS.
Original FUA effort has been started in [1] [1] https://lore.kernel.org/u-boot/20211019104049.v3.1.Ic581ec99f46b6dfa2e0b1922e670a333ac859e82@changeid/ Original-patch-by: Jon Lin <[email protected]> Signed-off-by: Denis Mukhin <[email protected]> --- I mentioned Jon's work under 'Orignal-patch-by' since current version differs quite a bit... Changes since v2: - new patch --- drivers/nvme/nvme.c | 17 +++++++++++++++++ drivers/nvme/nvme.h | 5 +++++ 2 files changed, 22 insertions(+) diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c index 2b14437f69c2..7bb6bb7b53f3 100644 --- a/drivers/nvme/nvme.c +++ b/drivers/nvme/nvme.c @@ -771,6 +771,13 @@ static ulong nvme_blk_rw(struct udevice *udev, lbaint_t blknr, c.rw.appmask = 0; c.rw.metadata = 0; + /* + * Enable force unit access (FUA) for data integrity if volatile write + * cache (VWC) is enabled. + */ + if (!read && (dev->flags & NVME_VWC_ENABLED)) + c.rw.control |= cpu_to_le16(NVME_RW_FUA); + while (total_lbas) { if (total_lbas < lbas) { lbas = (u16)total_lbas; @@ -899,6 +906,16 @@ int nvme_init(struct udevice *udev) if (!id->nsze) continue; + /* Check whether volatile write cache is enabled. */ + if (ndev->vwc & NVME_CTRL_VWC_PRESENT) { + u32 features; + + ret = nvme_get_features(ndev, NVME_FEAT_VOLATILE_WC, 0, 0, + &features); + if (!ret && (features & 0x1)) + ndev->flags |= NVME_VWC_ENABLED; + } + /* * Encode the namespace id to the device name so that * we can extract it when doing the probe. diff --git a/drivers/nvme/nvme.h b/drivers/nvme/nvme.h index bc1d612dde40..a938da728506 100644 --- a/drivers/nvme/nvme.h +++ b/drivers/nvme/nvme.h @@ -594,6 +594,10 @@ enum { NVME_CSTS_SHST_MASK = 3 << 2, }; +enum { + NVME_VWC_ENABLED = BIT(0), +}; + /* Represents an NVM Express device. Each nvme_dev is a PCI function. */ struct nvme_dev { struct udevice *udev; @@ -621,6 +625,7 @@ struct nvme_dev { u64 *prp_pool; u32 prp_entry_num; u32 nn; + unsigned int flags; }; /* Admin queue and a single I/O queue. */ -- 2.54.0

