* [PATCH v1 0/5] nvme: few fixups
@ 2026-05-28 1:20 dmukhin
2026-05-28 1:20 ` [PATCH v1 1/5] drivers: nvme: Log I/O timeouts dmukhin
` (4 more replies)
0 siblings, 5 replies; 15+ messages in thread
From: dmukhin @ 2026-05-28 1:20 UTC (permalink / raw)
To: u-boot; +Cc: sjg, trini, dmukhin
The series adds few fixes for NVMe subsystem.
Patch 1 adds logline for tracing misbehaving NVMe drives.
Patch 2 introduces NVMe flush command.
Patch 3 enables `nvme flush` for the currently selected NVMe drive.
Patch 4 makes nvme_shutdown() symbol public to enable use of it from
board_quiesce_devices()
Patch 5 tiny fixup for QEMU command for manual NVMe tests.
Denis Mukhin (5):
drivers: nvme: Log I/O timeouts
drivers: nvme: Implement NVMe flush command (0x0)
cmd: nvme: Add flush support
drivers: nvme: Export nvme_shutdown symbol
docs: nvme: Update QEMU command for testing
cmd/blk_common.c | 14 ++++++++++++++
cmd/nvme.c | 1 +
disk/disk-uclass.c | 6 ++++++
doc/develop/driver-model/nvme.rst | 2 +-
drivers/block/blk-uclass.c | 18 ++++++++++++++++++
drivers/nvme/nvme.c | 24 +++++++++++++++++++++++-
drivers/nvme/nvme.h | 7 -------
include/blk.h | 28 ++++++++++++++++++++++++++++
include/nvme.h | 11 +++++++++++
include/part.h | 8 ++++++++
10 files changed, 110 insertions(+), 9 deletions(-)
--
2.54.0
^ permalink raw reply [flat|nested] 15+ messages in thread* [PATCH v1 1/5] drivers: nvme: Log I/O timeouts 2026-05-28 1:20 [PATCH v1 0/5] nvme: few fixups dmukhin @ 2026-05-28 1:20 ` dmukhin 2026-05-28 9:11 ` Neil Armstrong 2026-05-28 1:20 ` [PATCH v1 2/5] drivers: nvme: Implement NVMe flush command (0x0) dmukhin ` (3 subsequent siblings) 4 siblings, 1 reply; 15+ messages in thread From: dmukhin @ 2026-05-28 1:20 UTC (permalink / raw) To: u-boot; +Cc: sjg, trini, dmukhin From: Denis Mukhin <dmukhin@ford.com> Current code silently swallows any timed-out commands scheduled to NVMe. Log those to be able to debug any potential problems with the NVMe hardware/firmware. Signed-off-by: Denis Mukhin <dmukhin@ford.com> --- drivers/nvme/nvme.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c index 0631b190b978..c3c44e50f19a 100644 --- a/drivers/nvme/nvme.c +++ b/drivers/nvme/nvme.c @@ -182,8 +182,10 @@ static int nvme_submit_sync_cmd(struct nvme_queue *nvmeq, if ((status & 0x01) == phase) break; if (timeout_us > 0 && (timer_get_us() - start_time) - >= timeout_us) + >= timeout_us) { + pr_warn("nvme: cmd %#x timed out\n", cmd->common.command_id); return -ETIMEDOUT; + } } ops = (struct nvme_ops *)nvmeq->dev->udev->driver->ops; -- 2.54.0 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v1 1/5] drivers: nvme: Log I/O timeouts 2026-05-28 1:20 ` [PATCH v1 1/5] drivers: nvme: Log I/O timeouts dmukhin @ 2026-05-28 9:11 ` Neil Armstrong 2026-05-29 3:25 ` dmukhin 0 siblings, 1 reply; 15+ messages in thread From: Neil Armstrong @ 2026-05-28 9:11 UTC (permalink / raw) To: dmukhin, u-boot; +Cc: sjg, trini On 5/28/26 03:20, dmukhin@ford.com wrote: > From: Denis Mukhin <dmukhin@ford.com> > > Current code silently swallows any timed-out commands scheduled > to NVMe. Log those to be able to debug any potential problems with > the NVMe hardware/firmware. > > Signed-off-by: Denis Mukhin <dmukhin@ford.com> > --- > drivers/nvme/nvme.c | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > > diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c > index 0631b190b978..c3c44e50f19a 100644 > --- a/drivers/nvme/nvme.c > +++ b/drivers/nvme/nvme.c > @@ -182,8 +182,10 @@ static int nvme_submit_sync_cmd(struct nvme_queue *nvmeq, > if ((status & 0x01) == phase) > break; > if (timeout_us > 0 && (timer_get_us() - start_time) > - >= timeout_us) > + >= timeout_us) { > + pr_warn("nvme: cmd %#x timed out\n", cmd->common.command_id); > return -ETIMEDOUT; > + } > } > > ops = (struct nvme_ops *)nvmeq->dev->udev->driver->ops; Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org> Thanks, Neil ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v1 1/5] drivers: nvme: Log I/O timeouts 2026-05-28 9:11 ` Neil Armstrong @ 2026-05-29 3:25 ` dmukhin 0 siblings, 0 replies; 15+ messages in thread From: dmukhin @ 2026-05-29 3:25 UTC (permalink / raw) To: Neil Armstrong; +Cc: dmukhin, u-boot, sjg, trini On Thu, May 28, 2026 at 11:11:35AM +0200, Neil Armstrong wrote: > On 5/28/26 03:20, dmukhin@ford.com wrote: > > From: Denis Mukhin <dmukhin@ford.com> > > > > Current code silently swallows any timed-out commands scheduled > > to NVMe. Log those to be able to debug any potential problems with > > the NVMe hardware/firmware. > > > > Signed-off-by: Denis Mukhin <dmukhin@ford.com> > > --- > > drivers/nvme/nvme.c | 4 +++- > > 1 file changed, 3 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c > > index 0631b190b978..c3c44e50f19a 100644 > > --- a/drivers/nvme/nvme.c > > +++ b/drivers/nvme/nvme.c > > @@ -182,8 +182,10 @@ static int nvme_submit_sync_cmd(struct nvme_queue *nvmeq, > > if ((status & 0x01) == phase) > > break; > > if (timeout_us > 0 && (timer_get_us() - start_time) > > - >= timeout_us) > > + >= timeout_us) { > > + pr_warn("nvme: cmd %#x timed out\n", cmd->common.command_id); > > return -ETIMEDOUT; > > + } > > } > > ops = (struct nvme_ops *)nvmeq->dev->udev->driver->ops; > > Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org> Thank you! > > Thanks, > Neil ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v1 2/5] drivers: nvme: Implement NVMe flush command (0x0) 2026-05-28 1:20 [PATCH v1 0/5] nvme: few fixups dmukhin 2026-05-28 1:20 ` [PATCH v1 1/5] drivers: nvme: Log I/O timeouts dmukhin @ 2026-05-28 1:20 ` dmukhin 2026-05-28 9:28 ` Neil Armstrong 2026-05-28 1:20 ` [PATCH v1 3/5] cmd: nvme: Add flush support dmukhin ` (2 subsequent siblings) 4 siblings, 1 reply; 15+ messages in thread From: dmukhin @ 2026-05-28 1:20 UTC (permalink / raw) To: u-boot; +Cc: sjg, trini, dmukhin From: Denis Mukhin <dmukhin@ford.com> Add flush command implementation along with a high-level disk_blk_flush() API to be called at certain checkpoints during the boot (e.g. updating custom bootflow flags stored on NVMe). Signed-off-by: Denis Mukhin <dmukhin@ford.com> --- disk/disk-uclass.c | 6 ++++++ drivers/block/blk-uclass.c | 18 ++++++++++++++++++ drivers/nvme/nvme.c | 20 ++++++++++++++++++++ include/blk.h | 28 ++++++++++++++++++++++++++++ include/part.h | 8 ++++++++ 5 files changed, 80 insertions(+) diff --git a/disk/disk-uclass.c b/disk/disk-uclass.c index ee3cc4407d76..b04b6306e5f2 100644 --- a/disk/disk-uclass.c +++ b/disk/disk-uclass.c @@ -122,6 +122,11 @@ unsigned long disk_blk_erase(struct udevice *dev, lbaint_t start, blkcnt); } +unsigned long disk_blk_flush(struct udevice *dev) +{ + return blk_flush(dev_get_parent(dev)); +} + UCLASS_DRIVER(partition) = { .id = UCLASS_PARTITION, .per_device_plat_auto = sizeof(struct disk_part), @@ -132,6 +137,7 @@ static const struct blk_ops blk_part_ops = { .read = disk_blk_read, .write = disk_blk_write, .erase = disk_blk_erase, + .flush = disk_blk_flush, }; U_BOOT_DRIVER(blk_partition) = { diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 73c24fd91763..0be1fdab1ba5 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -514,6 +514,19 @@ long blk_erase(struct udevice *dev, lbaint_t start, lbaint_t blkcnt) return ops->erase(dev, start, blkcnt); } +long blk_flush(struct udevice *dev) +{ + struct blk_desc *desc = dev_get_uclass_plat(dev); + const struct blk_ops *ops = blk_get_ops(dev); + + if (!ops->flush) + return -ENOSYS; + + blkcache_invalidate(desc->uclass_id, desc->devnum); + + return ops->flush(dev); +} + ulong blk_dread(struct blk_desc *desc, lbaint_t start, lbaint_t blkcnt, void *buffer) { @@ -531,6 +544,11 @@ ulong blk_derase(struct blk_desc *desc, lbaint_t start, lbaint_t blkcnt) return blk_erase(desc->bdev, start, blkcnt); } +ulong blk_dflush(struct blk_desc *desc) +{ + return blk_flush(desc->bdev); +} + int blk_find_from_parent(struct udevice *parent, struct udevice **devp) { struct udevice *dev; diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c index c3c44e50f19a..d9f099a11593 100644 --- a/drivers/nvme/nvme.c +++ b/drivers/nvme/nvme.c @@ -819,9 +819,29 @@ static ulong nvme_blk_write(struct udevice *udev, lbaint_t blknr, return nvme_blk_rw(udev, blknr, blkcnt, (void *)buffer, false); } +/* + * NVM Flush command (opcode 0x00). + * + * Applies to a single namespace; the controller must commit all dirty + * data for that namespace to storage before completing the command. + */ +static ulong nvme_blk_flush(struct udevice *udev) +{ + struct nvme_ns *ns = dev_get_priv(udev); + struct nvme_dev *dev = ns->dev; + struct nvme_command c; + + memset(&c, 0, sizeof(c)); + c.common.opcode = nvme_cmd_flush; + c.common.nsid = cpu_to_le32(ns->ns_id); + + return nvme_submit_sync_cmd(dev->queues[NVME_IO_Q], &c, NULL, IO_TIMEOUT); +} + static const struct blk_ops nvme_blk_ops = { .read = nvme_blk_read, .write = nvme_blk_write, + .flush = nvme_blk_flush, }; U_BOOT_DRIVER(nvme_blk) = { diff --git a/include/blk.h b/include/blk.h index 8d1b70cabd31..3e2160a1ae4d 100644 --- a/include/blk.h +++ b/include/blk.h @@ -99,6 +99,7 @@ struct blk_desc { unsigned long (*block_erase)(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt); + unsigned long (*block_flush)(struct blk_desc *block_dev); void *priv; /* driver private struct pointer */ #endif }; @@ -275,6 +276,14 @@ struct blk_ops { */ int (*buffer_aligned)(struct udevice *dev, struct bounce_buffer *state); #endif /* CONFIG_BOUNCE_BUFFER */ + + /** + * flush() - commit all dirty data to storage + * + * @dev: Device to flush + * @return 0 if OK, -ve on error + */ + unsigned long (*flush)(struct udevice *dev); }; #if CONFIG_IS_ENABLED(BLK) @@ -291,6 +300,7 @@ unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, const void *buffer); unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt); +unsigned long blk_dflush(struct blk_desc *block_dev); #endif /* BLK */ @@ -331,6 +341,14 @@ long blk_write(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, */ long blk_erase(struct udevice *dev, lbaint_t start, lbaint_t blkcnt); +/** + * blk_flush() - Commit data to a block device + * + * @dev: Device to flush + * @return 0 if operation succeeded, or -ve on error. + */ +long blk_flush(struct udevice *dev); + /** * blk_find_device() - Find a block device * @@ -559,6 +577,16 @@ static inline ulong blk_derase(struct blk_desc *block_dev, lbaint_t start, return block_dev->block_erase(block_dev, start, blkcnt); } +static inline ulong blk_dflush(struct blk_desc *block_dev) +{ + blkcache_invalidate(block_dev->uclass_id, block_dev->devnum); + + if (block_dev->block_flush) + return block_dev->block_flush(block_dev); + + return 0; +} + /** * struct blk_driver - Driver for block interface types * diff --git a/include/part.h b/include/part.h index 15daacd7faaa..63982d7b9370 100644 --- a/include/part.h +++ b/include/part.h @@ -454,6 +454,14 @@ ulong disk_blk_write(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, */ ulong disk_blk_erase(struct udevice *dev, lbaint_t start, lbaint_t blkcnt); +/** + * disk_blk_flush() - commit data to a disk + * + * @dev: Device to flush + * Return: 0 success, or -ve error number (see the IS_ERR_VALUE() macro + */ +ulong disk_blk_flush(struct udevice *dev); + /* * We don't support printing partition information in SPL and only support * getting partition information in a few cases. -- 2.54.0 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v1 2/5] drivers: nvme: Implement NVMe flush command (0x0) 2026-05-28 1:20 ` [PATCH v1 2/5] drivers: nvme: Implement NVMe flush command (0x0) dmukhin @ 2026-05-28 9:28 ` Neil Armstrong 2026-05-29 3:36 ` dmukhin 0 siblings, 1 reply; 15+ messages in thread From: Neil Armstrong @ 2026-05-28 9:28 UTC (permalink / raw) To: dmukhin, u-boot; +Cc: sjg, trini Hi, On 5/28/26 03:20, dmukhin@ford.com wrote: > From: Denis Mukhin <dmukhin@ford.com> > > Add flush command implementation along with a high-level > disk_blk_flush() API to be called at certain checkpoints > during the boot (e.g. updating custom bootflow flags stored > on NVMe). First general comment, please split the patch by adding the flush infrastructure first and then the nvme support. The for NVMe, can it support write-through like SCSI FUA (Force Unit Access) which bypasses the cache on writes, with slower writes but safer and simpler than calling a flush before OS boot. > > Signed-off-by: Denis Mukhin <dmukhin@ford.com> > --- > disk/disk-uclass.c | 6 ++++++ > drivers/block/blk-uclass.c | 18 ++++++++++++++++++ > drivers/nvme/nvme.c | 20 ++++++++++++++++++++ > include/blk.h | 28 ++++++++++++++++++++++++++++ > include/part.h | 8 ++++++++ > 5 files changed, 80 insertions(+) > > diff --git a/disk/disk-uclass.c b/disk/disk-uclass.c > index ee3cc4407d76..b04b6306e5f2 100644 > --- a/disk/disk-uclass.c > +++ b/disk/disk-uclass.c > @@ -122,6 +122,11 @@ unsigned long disk_blk_erase(struct udevice *dev, lbaint_t start, > blkcnt); > } > > +unsigned long disk_blk_flush(struct udevice *dev) > +{ > + return blk_flush(dev_get_parent(dev)); > +} > + > UCLASS_DRIVER(partition) = { > .id = UCLASS_PARTITION, > .per_device_plat_auto = sizeof(struct disk_part), > @@ -132,6 +137,7 @@ static const struct blk_ops blk_part_ops = { > .read = disk_blk_read, > .write = disk_blk_write, > .erase = disk_blk_erase, > + .flush = disk_blk_flush, > }; > > U_BOOT_DRIVER(blk_partition) = { > diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c > index 73c24fd91763..0be1fdab1ba5 100644 > --- a/drivers/block/blk-uclass.c > +++ b/drivers/block/blk-uclass.c > @@ -514,6 +514,19 @@ long blk_erase(struct udevice *dev, lbaint_t start, lbaint_t blkcnt) > return ops->erase(dev, start, blkcnt); > } > > +long blk_flush(struct udevice *dev) > +{ > + struct blk_desc *desc = dev_get_uclass_plat(dev); > + const struct blk_ops *ops = blk_get_ops(dev); > + > + if (!ops->flush) > + return -ENOSYS; > + > + blkcache_invalidate(desc->uclass_id, desc->devnum); > + > + return ops->flush(dev); > +} > + > ulong blk_dread(struct blk_desc *desc, lbaint_t start, lbaint_t blkcnt, > void *buffer) > { > @@ -531,6 +544,11 @@ ulong blk_derase(struct blk_desc *desc, lbaint_t start, lbaint_t blkcnt) > return blk_erase(desc->bdev, start, blkcnt); > } > > +ulong blk_dflush(struct blk_desc *desc) > +{ > + return blk_flush(desc->bdev); > +} > + > int blk_find_from_parent(struct udevice *parent, struct udevice **devp) > { > struct udevice *dev; > diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c > index c3c44e50f19a..d9f099a11593 100644 > --- a/drivers/nvme/nvme.c > +++ b/drivers/nvme/nvme.c > @@ -819,9 +819,29 @@ static ulong nvme_blk_write(struct udevice *udev, lbaint_t blknr, > return nvme_blk_rw(udev, blknr, blkcnt, (void *)buffer, false); > } > > +/* > + * NVM Flush command (opcode 0x00). > + * > + * Applies to a single namespace; the controller must commit all dirty > + * data for that namespace to storage before completing the command. > + */ > +static ulong nvme_blk_flush(struct udevice *udev) > +{ > + struct nvme_ns *ns = dev_get_priv(udev); > + struct nvme_dev *dev = ns->dev; > + struct nvme_command c; > + > + memset(&c, 0, sizeof(c)); > + c.common.opcode = nvme_cmd_flush; > + c.common.nsid = cpu_to_le32(ns->ns_id); > + > + return nvme_submit_sync_cmd(dev->queues[NVME_IO_Q], &c, NULL, IO_TIMEOUT); > +} > + > static const struct blk_ops nvme_blk_ops = { > .read = nvme_blk_read, > .write = nvme_blk_write, > + .flush = nvme_blk_flush, > }; > > U_BOOT_DRIVER(nvme_blk) = { > diff --git a/include/blk.h b/include/blk.h > index 8d1b70cabd31..3e2160a1ae4d 100644 > --- a/include/blk.h > +++ b/include/blk.h > @@ -99,6 +99,7 @@ struct blk_desc { > unsigned long (*block_erase)(struct blk_desc *block_dev, > lbaint_t start, > lbaint_t blkcnt); > + unsigned long (*block_flush)(struct blk_desc *block_dev); > void *priv; /* driver private struct pointer */ > #endif > }; > @@ -275,6 +276,14 @@ struct blk_ops { > */ > int (*buffer_aligned)(struct udevice *dev, struct bounce_buffer *state); > #endif /* CONFIG_BOUNCE_BUFFER */ > + > + /** > + * flush() - commit all dirty data to storage > + * > + * @dev: Device to flush > + * @return 0 if OK, -ve on error > + */ > + unsigned long (*flush)(struct udevice *dev); > }; > > #if CONFIG_IS_ENABLED(BLK) > @@ -291,6 +300,7 @@ unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start, > lbaint_t blkcnt, const void *buffer); > unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start, > lbaint_t blkcnt); > +unsigned long blk_dflush(struct blk_desc *block_dev); > > #endif /* BLK */ > > @@ -331,6 +341,14 @@ long blk_write(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, > */ > long blk_erase(struct udevice *dev, lbaint_t start, lbaint_t blkcnt); > > +/** > + * blk_flush() - Commit data to a block device > + * > + * @dev: Device to flush > + * @return 0 if operation succeeded, or -ve on error. > + */ > +long blk_flush(struct udevice *dev); > + > /** > * blk_find_device() - Find a block device > * > @@ -559,6 +577,16 @@ static inline ulong blk_derase(struct blk_desc *block_dev, lbaint_t start, > return block_dev->block_erase(block_dev, start, blkcnt); > } > > +static inline ulong blk_dflush(struct blk_desc *block_dev) > +{ > + blkcache_invalidate(block_dev->uclass_id, block_dev->devnum); Call blkcache_invalidate only if flush cmd is supported > + > + if (block_dev->block_flush) > + return block_dev->block_flush(block_dev); > + > + return 0; Why do you return success here and not from blk_flush() when flush is not supported? > +} > + > /** > * struct blk_driver - Driver for block interface types > * > diff --git a/include/part.h b/include/part.h > index 15daacd7faaa..63982d7b9370 100644 > --- a/include/part.h > +++ b/include/part.h > @@ -454,6 +454,14 @@ ulong disk_blk_write(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, > */ > ulong disk_blk_erase(struct udevice *dev, lbaint_t start, lbaint_t blkcnt); > > +/** > + * disk_blk_flush() - commit data to a disk > + * > + * @dev: Device to flush > + * Return: 0 success, or -ve error number (see the IS_ERR_VALUE() macro > + */ > +ulong disk_blk_flush(struct udevice *dev); > + > /* > * We don't support printing partition information in SPL and only support > * getting partition information in a few cases. Thanks, Neil ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v1 2/5] drivers: nvme: Implement NVMe flush command (0x0) 2026-05-28 9:28 ` Neil Armstrong @ 2026-05-29 3:36 ` dmukhin 2026-05-29 7:54 ` Neil Armstrong 0 siblings, 1 reply; 15+ messages in thread From: dmukhin @ 2026-05-29 3:36 UTC (permalink / raw) To: Neil Armstrong; +Cc: dmukhin, u-boot, sjg, trini On Thu, May 28, 2026 at 11:28:33AM +0200, Neil Armstrong wrote: > Hi, > > On 5/28/26 03:20, dmukhin@ford.com wrote: > > From: Denis Mukhin <dmukhin@ford.com> > > > > Add flush command implementation along with a high-level > > disk_blk_flush() API to be called at certain checkpoints > > during the boot (e.g. updating custom bootflow flags stored > > on NVMe). > > First general comment, please split the patch by adding the > flush infrastructure first and then the nvme support. Will do, thanks. > > The for NVMe, can it support write-through like SCSI FUA (Force Unit > Access) which bypasses the cache on writes, with slower writes > but safer and simpler than calling a flush before OS boot. Yes, I've seen there was FUA patch [1], which was then reverted [2]. For our purposes, flush seems to be enough: the use case is updating NVMe-backed boot counter from a custom bootflow. [1] https://lore.kernel.org/u-boot/20211019104049.v3.1.Ic581ec99f46b6dfa2e0b1922e670a333ac859e82@changeid/ [2] https://lore.kernel.org/u-boot/CAGi-RUL96GK5nfHx73UQQd_4sFByt3gNwqhFpHps+h58S20JwQ@mail.gmail.com/ [..] > > /** > > * blk_find_device() - Find a block device > > * > > @@ -559,6 +577,16 @@ static inline ulong blk_derase(struct blk_desc *block_dev, lbaint_t start, > > return block_dev->block_erase(block_dev, start, blkcnt); > > } > > +static inline ulong blk_dflush(struct blk_desc *block_dev) > > +{ > > + blkcache_invalidate(block_dev->uclass_id, block_dev->devnum); > > Call blkcache_invalidate only if flush cmd is supported Ack. > > > + > > + if (block_dev->block_flush) > > + return block_dev->block_flush(block_dev); > > + > > + return 0; > > Why do you return success here and not from blk_flush() when flush is not supported? Will update. Thanks, Denis ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v1 2/5] drivers: nvme: Implement NVMe flush command (0x0) 2026-05-29 3:36 ` dmukhin @ 2026-05-29 7:54 ` Neil Armstrong 2026-06-05 3:43 ` dmukhin 0 siblings, 1 reply; 15+ messages in thread From: Neil Armstrong @ 2026-05-29 7:54 UTC (permalink / raw) To: dmukhin; +Cc: u-boot, sjg, trini On 5/29/26 05:36, dmukhin@ford.com wrote: > On Thu, May 28, 2026 at 11:28:33AM +0200, Neil Armstrong wrote: >> Hi, >> >> On 5/28/26 03:20, dmukhin@ford.com wrote: >>> From: Denis Mukhin <dmukhin@ford.com> >>> >>> Add flush command implementation along with a high-level >>> disk_blk_flush() API to be called at certain checkpoints >>> during the boot (e.g. updating custom bootflow flags stored >>> on NVMe). >> >> First general comment, please split the patch by adding the >> flush infrastructure first and then the nvme support. > > Will do, thanks. > >> >> The for NVMe, can it support write-through like SCSI FUA (Force Unit >> Access) which bypasses the cache on writes, with slower writes >> but safer and simpler than calling a flush before OS boot. > > Yes, I've seen there was FUA patch [1], which was then reverted [2]. > > For our purposes, flush seems to be enough: the use case is > updating NVMe-backed boot counter from a custom bootflow. OK the FUA was reverted because Bin's comment was not adressed: https://lore.kernel.org/u-boot/CAEUhbmU02GnqEEfuqNrSj8R5XEZkmkTUaLp1+BMbYQNdzTUZ7A@mail.gmail.com/ I would prefer having FUA added so all board could have this enabled and not have to update their boot flow to call flush, this was basically why the SCSI FUA was enabled. As Bin's comment, perhaps a way would be to disable the Write Cache if the cache is present as init time (WCE), and it's even simpler, or get the enable state of the WC and use FUA if enabled. Because the same question remains with the flush command, it's only valid if the WC is present and is enabled. Thanks, Neil > > [1] https://lore.kernel.org/u-boot/20211019104049.v3.1.Ic581ec99f46b6dfa2e0b1922e670a333ac859e82@changeid/ > [2] https://lore.kernel.org/u-boot/CAGi-RUL96GK5nfHx73UQQd_4sFByt3gNwqhFpHps+h58S20JwQ@mail.gmail.com/ > > [..] >>> /** >>> * blk_find_device() - Find a block device >>> * >>> @@ -559,6 +577,16 @@ static inline ulong blk_derase(struct blk_desc *block_dev, lbaint_t start, >>> return block_dev->block_erase(block_dev, start, blkcnt); >>> } >>> +static inline ulong blk_dflush(struct blk_desc *block_dev) >>> +{ >>> + blkcache_invalidate(block_dev->uclass_id, block_dev->devnum); >> >> Call blkcache_invalidate only if flush cmd is supported > > Ack. > >> >>> + >>> + if (block_dev->block_flush) >>> + return block_dev->block_flush(block_dev); >>> + >>> + return 0; >> >> Why do you return success here and not from blk_flush() when flush is not supported? > > Will update. > > > Thanks, > Denis ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v1 2/5] drivers: nvme: Implement NVMe flush command (0x0) 2026-05-29 7:54 ` Neil Armstrong @ 2026-06-05 3:43 ` dmukhin 2026-06-05 8:01 ` Neil Armstrong 0 siblings, 1 reply; 15+ messages in thread From: dmukhin @ 2026-06-05 3:43 UTC (permalink / raw) To: Neil Armstrong; +Cc: dmukhin, u-boot, sjg, trini Hi Neil, Thanks for your feedback! Sorry, it took me a while to respond. On Fri, May 29, 2026 at 09:54:32AM +0200, Neil Armstrong wrote: [..] > > > > > > > > The for NVMe, can it support write-through like SCSI FUA (Force Unit > > > Access) which bypasses the cache on writes, with slower writes > > > but safer and simpler than calling a flush before OS boot. > > > > Yes, I've seen there was FUA patch [1], which was then reverted [2]. > > > > For our purposes, flush seems to be enough: the use case is > > updating NVMe-backed boot counter from a custom bootflow. > > OK the FUA was reverted because Bin's comment was not adressed: > https://lore.kernel.org/u-boot/CAEUhbmU02GnqEEfuqNrSj8R5XEZkmkTUaLp1+BMbYQNdzTUZ7A@mail.gmail.com/ > > I would prefer having FUA added so all board could have this enabled > and not have to update their boot flow to call flush, this was basically > why the SCSI FUA was enabled. I will take a look into FUA. The problem I was solving is providing a guarantee that GPT headers will be updated correctly on the NVMe device. I have a new bootcount device which implements a counter backed by GPT PTE flags (the top 16 bits) [1] Patch [2] adds new APIs to update 16 bit flags in both primary and backup GPT headers (the proposed write_gpt_pte() call). This is where I originally used new flush command: to guarantee that NVMe received all the updates before it is handed over to the OS. [1] https://lore.kernel.org/u-boot/20260605033907.1909319-1-dmukhin@ford.com/ [2] https://lore.kernel.org/u-boot/20260605033907.1909319-3-dmukhin@ford.com/ > > As Bin's comment, perhaps a way would be to disable the Write Cache if > the cache is present as init time (WCE), and it's even simpler, or > get the enable state of the WC and use FUA if enabled. > > Because the same question remains with the flush command, it's > only valid if the WC is present and is enabled. > > Thanks, > Neil > > > > > [1] https://lore.kernel.org/u-boot/20211019104049.v3.1.Ic581ec99f46b6dfa2e0b1922e670a333ac859e82@changeid/ > > [2] https://lore.kernel.org/u-boot/CAGi-RUL96GK5nfHx73UQQd_4sFByt3gNwqhFpHps+h58S20JwQ@mail.gmail.com/ -- Denis ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v1 2/5] drivers: nvme: Implement NVMe flush command (0x0) 2026-06-05 3:43 ` dmukhin @ 2026-06-05 8:01 ` Neil Armstrong 0 siblings, 0 replies; 15+ messages in thread From: Neil Armstrong @ 2026-06-05 8:01 UTC (permalink / raw) To: dmukhin; +Cc: u-boot, sjg, trini On 6/5/26 05:43, dmukhin@ford.com wrote: > Hi Neil, > > Thanks for your feedback! > > Sorry, it took me a while to respond. > > On Fri, May 29, 2026 at 09:54:32AM +0200, Neil Armstrong wrote: > [..] >>> >>>> >>>> The for NVMe, can it support write-through like SCSI FUA (Force Unit >>>> Access) which bypasses the cache on writes, with slower writes >>>> but safer and simpler than calling a flush before OS boot. >>> >>> Yes, I've seen there was FUA patch [1], which was then reverted [2]. >>> >>> For our purposes, flush seems to be enough: the use case is >>> updating NVMe-backed boot counter from a custom bootflow. >> >> OK the FUA was reverted because Bin's comment was not adressed: >> https://lore.kernel.org/u-boot/CAEUhbmU02GnqEEfuqNrSj8R5XEZkmkTUaLp1+BMbYQNdzTUZ7A@mail.gmail.com/ >> >> I would prefer having FUA added so all board could have this enabled >> and not have to update their boot flow to call flush, this was basically >> why the SCSI FUA was enabled. > > I will take a look into FUA. > > The problem I was solving is providing a guarantee that GPT headers > will be updated correctly on the NVMe device. > > I have a new bootcount device which implements a counter backed by > GPT PTE flags (the top 16 bits) [1] > > Patch [2] adds new APIs to update 16 bit flags in both primary and > backup GPT headers (the proposed write_gpt_pte() call). > > This is where I originally used new flush command: to guarantee that > NVMe received all the updates before it is handed over to the OS. I understand that, this is why FUA or disabling WC is exactly the same, will beneficiate to all platforms and avoid calling flush everytime at the cost of some small performance penalty since the NVMe driver isn't performance optimized anyway. Neil > > [1] https://lore.kernel.org/u-boot/20260605033907.1909319-1-dmukhin@ford.com/ > [2] https://lore.kernel.org/u-boot/20260605033907.1909319-3-dmukhin@ford.com/ > >> >> As Bin's comment, perhaps a way would be to disable the Write Cache if >> the cache is present as init time (WCE), and it's even simpler, or >> get the enable state of the WC and use FUA if enabled. >> >> Because the same question remains with the flush command, it's >> only valid if the WC is present and is enabled. >> >> Thanks, >> Neil >> >>> >>> [1] https://lore.kernel.org/u-boot/20211019104049.v3.1.Ic581ec99f46b6dfa2e0b1922e670a333ac859e82@changeid/ >>> [2] https://lore.kernel.org/u-boot/CAGi-RUL96GK5nfHx73UQQd_4sFByt3gNwqhFpHps+h58S20JwQ@mail.gmail.com/ > > -- > Denis ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v1 3/5] cmd: nvme: Add flush support 2026-05-28 1:20 [PATCH v1 0/5] nvme: few fixups dmukhin 2026-05-28 1:20 ` [PATCH v1 1/5] drivers: nvme: Log I/O timeouts dmukhin 2026-05-28 1:20 ` [PATCH v1 2/5] drivers: nvme: Implement NVMe flush command (0x0) dmukhin @ 2026-05-28 1:20 ` dmukhin 2026-05-28 9:29 ` Neil Armstrong 2026-05-28 1:20 ` [PATCH v1 4/5] drivers: nvme: Export nvme_shutdown symbol dmukhin 2026-05-28 1:20 ` [PATCH v1 5/5] docs: nvme: Update QEMU command for testing dmukhin 4 siblings, 1 reply; 15+ messages in thread From: dmukhin @ 2026-05-28 1:20 UTC (permalink / raw) To: u-boot; +Cc: sjg, trini, dmukhin From: Denis Mukhin <dmukhin@ford.com> Introduce `nvme flush` to allow users to commit all dirty data explicitly to the current NVMe device. Signed-off-by: Denis Mukhin <dmukhin@ford.com> --- cmd/blk_common.c | 14 ++++++++++++++ cmd/nvme.c | 1 + 2 files changed, 15 insertions(+) diff --git a/cmd/blk_common.c b/cmd/blk_common.c index 56529702a470..d3b00e10f17c 100644 --- a/cmd/blk_common.c +++ b/cmd/blk_common.c @@ -37,6 +37,20 @@ int blk_common_cmd(int argc, char *const argv[], enum uclass_id uclass_id, printf("\nno %s partition table available\n", if_name); return CMD_RET_SUCCESS; + } else if (strncmp(argv[1], "flush", 5) == 0) { + struct blk_desc *desc; + int ret; + + ret = blk_get_desc(uclass_id, *cur_devnump, &desc); + if (ret) + return CMD_RET_FAILURE; + + if (blk_dflush(desc)) { + printf("\nfailed to flush device %s\n", if_name); + return CMD_RET_FAILURE; + } + + return CMD_RET_SUCCESS; } return CMD_RET_USAGE; case 3: diff --git a/cmd/nvme.c b/cmd/nvme.c index f2c9acba5c32..21ac9a6fac7a 100644 --- a/cmd/nvme.c +++ b/cmd/nvme.c @@ -46,6 +46,7 @@ U_BOOT_CMD( "NVM Express sub-system", "scan - scan NVMe devices\n" "nvme detail - show details of current NVMe device\n" + "nvme flush - commit all dirty data to the current NVMe device\n" "nvme info - show all available NVMe devices\n" "nvme device [dev] - show or set current NVMe device\n" "nvme part [dev] - print partition table of one or all NVMe devices\n" -- 2.54.0 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v1 3/5] cmd: nvme: Add flush support 2026-05-28 1:20 ` [PATCH v1 3/5] cmd: nvme: Add flush support dmukhin @ 2026-05-28 9:29 ` Neil Armstrong 2026-05-29 3:36 ` dmukhin 0 siblings, 1 reply; 15+ messages in thread From: Neil Armstrong @ 2026-05-28 9:29 UTC (permalink / raw) To: dmukhin, u-boot; +Cc: sjg, trini On 5/28/26 03:20, dmukhin@ford.com wrote: > From: Denis Mukhin <dmukhin@ford.com> > > Introduce `nvme flush` to allow users to commit all dirty data explicitly > to the current NVMe device. This adds flush for all blk devices, please rewrite the commit subject, message and update all blk commands and not only nvme. > > Signed-off-by: Denis Mukhin <dmukhin@ford.com> > --- > cmd/blk_common.c | 14 ++++++++++++++ > cmd/nvme.c | 1 + > 2 files changed, 15 insertions(+) > > diff --git a/cmd/blk_common.c b/cmd/blk_common.c > index 56529702a470..d3b00e10f17c 100644 > --- a/cmd/blk_common.c > +++ b/cmd/blk_common.c > @@ -37,6 +37,20 @@ int blk_common_cmd(int argc, char *const argv[], enum uclass_id uclass_id, > printf("\nno %s partition table available\n", > if_name); > return CMD_RET_SUCCESS; > + } else if (strncmp(argv[1], "flush", 5) == 0) { > + struct blk_desc *desc; > + int ret; > + > + ret = blk_get_desc(uclass_id, *cur_devnump, &desc); > + if (ret) > + return CMD_RET_FAILURE; > + > + if (blk_dflush(desc)) { > + printf("\nfailed to flush device %s\n", if_name); > + return CMD_RET_FAILURE; > + } > + > + return CMD_RET_SUCCESS; > } > return CMD_RET_USAGE; > case 3: > diff --git a/cmd/nvme.c b/cmd/nvme.c > index f2c9acba5c32..21ac9a6fac7a 100644 > --- a/cmd/nvme.c > +++ b/cmd/nvme.c > @@ -46,6 +46,7 @@ U_BOOT_CMD( > "NVM Express sub-system", > "scan - scan NVMe devices\n" > "nvme detail - show details of current NVMe device\n" > + "nvme flush - commit all dirty data to the current NVMe device\n" > "nvme info - show all available NVMe devices\n" > "nvme device [dev] - show or set current NVMe device\n" > "nvme part [dev] - print partition table of one or all NVMe devices\n" ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v1 3/5] cmd: nvme: Add flush support 2026-05-28 9:29 ` Neil Armstrong @ 2026-05-29 3:36 ` dmukhin 0 siblings, 0 replies; 15+ messages in thread From: dmukhin @ 2026-05-29 3:36 UTC (permalink / raw) To: Neil Armstrong; +Cc: dmukhin, u-boot, sjg, trini On Thu, May 28, 2026 at 11:29:51AM +0200, Neil Armstrong wrote: > On 5/28/26 03:20, dmukhin@ford.com wrote: > > From: Denis Mukhin <dmukhin@ford.com> > > > > Introduce `nvme flush` to allow users to commit all dirty data explicitly > > to the current NVMe device. > > This adds flush for all blk devices, please rewrite > the commit subject, message and update all blk commands > and not only nvme. Will update, thanks! -- Denis ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v1 4/5] drivers: nvme: Export nvme_shutdown symbol 2026-05-28 1:20 [PATCH v1 0/5] nvme: few fixups dmukhin ` (2 preceding siblings ...) 2026-05-28 1:20 ` [PATCH v1 3/5] cmd: nvme: Add flush support dmukhin @ 2026-05-28 1:20 ` dmukhin 2026-05-28 1:20 ` [PATCH v1 5/5] docs: nvme: Update QEMU command for testing dmukhin 4 siblings, 0 replies; 15+ messages in thread From: dmukhin @ 2026-05-28 1:20 UTC (permalink / raw) To: u-boot; +Cc: sjg, trini, dmukhin From: Denis Mukhin <dmukhin@ford.com> Make nvme_shutdown() public so that it can be re-used in board-specific board_quiesce_devices() before OS hand-off. Signed-off-by: Denis Mukhin <dmukhin@ford.com> --- drivers/nvme/nvme.h | 7 ------- include/nvme.h | 11 +++++++++++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/nvme/nvme.h b/drivers/nvme/nvme.h index bc1d612dde40..25a8b0b17772 100644 --- a/drivers/nvme/nvme.h +++ b/drivers/nvme/nvme.h @@ -698,11 +698,4 @@ struct nvme_ops { */ int nvme_init(struct udevice *udev); -/** - * nvme_shutdown() - Shutdown NVM Express device - * @udev: The NVM Express device - * Return: 0 if OK, -ve on error - */ -int nvme_shutdown(struct udevice *udev); - #endif /* __DRIVER_NVME_H__ */ diff --git a/include/nvme.h b/include/nvme.h index 2cdf8ce320c1..c7b301300097 100644 --- a/include/nvme.h +++ b/include/nvme.h @@ -90,4 +90,15 @@ int nvme_print_info(struct udevice *udev); */ int nvme_get_namespace_id(struct udevice *udev, u32 *ns_id, u8 *eui64); +/** + * nvme_shutdown() - Shutdown NVM Express device + * + * Must be called before booting an OS to ensure cache is flushed + * and the controller is in a clean state for OS to re-initialize. + * + * @udev: The NVM Express device + * Return: 0 if OK, -ve on error + */ +int nvme_shutdown(struct udevice *udev); + #endif /* __NVME_H__ */ -- 2.54.0 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v1 5/5] docs: nvme: Update QEMU command for testing 2026-05-28 1:20 [PATCH v1 0/5] nvme: few fixups dmukhin ` (3 preceding siblings ...) 2026-05-28 1:20 ` [PATCH v1 4/5] drivers: nvme: Export nvme_shutdown symbol dmukhin @ 2026-05-28 1:20 ` dmukhin 4 siblings, 0 replies; 15+ messages in thread From: dmukhin @ 2026-05-28 1:20 UTC (permalink / raw) To: u-boot; +Cc: sjg, trini, dmukhin From: Denis Mukhin <dmukhin@ford.com> Switch to x86-64 QEMU machine for NVMe testing in the docs. Also, add `format=raw` for empty NVMe disks QEMU command line. Signed-off-by: Denis Mukhin <dmukhin@ford.com> --- doc/develop/driver-model/nvme.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/develop/driver-model/nvme.rst b/doc/develop/driver-model/nvme.rst index 755181331213..0e0624925e0d 100644 --- a/doc/develop/driver-model/nvme.rst +++ b/doc/develop/driver-model/nvme.rst @@ -95,4 +95,4 @@ Example command line to call QEMU x86 below with emulated NVMe device: .. code-block:: bash - $ ./qemu-system-i386 -drive file=nvme.img,if=none,id=drv0 -device nvme,drive=drv0,serial=QEMUNVME0001 -bios u-boot.rom + $ qemu-system-x86_64 -nographic -drive file=nvme.img,format=raw,if=none,id=drv0 -device nvme,drive=drv0,serial=QEMUNVME0001 -bios u-boot.rom -- 2.54.0 ^ permalink raw reply related [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-06-05 8:01 UTC | newest] Thread overview: 15+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-05-28 1:20 [PATCH v1 0/5] nvme: few fixups dmukhin 2026-05-28 1:20 ` [PATCH v1 1/5] drivers: nvme: Log I/O timeouts dmukhin 2026-05-28 9:11 ` Neil Armstrong 2026-05-29 3:25 ` dmukhin 2026-05-28 1:20 ` [PATCH v1 2/5] drivers: nvme: Implement NVMe flush command (0x0) dmukhin 2026-05-28 9:28 ` Neil Armstrong 2026-05-29 3:36 ` dmukhin 2026-05-29 7:54 ` Neil Armstrong 2026-06-05 3:43 ` dmukhin 2026-06-05 8:01 ` Neil Armstrong 2026-05-28 1:20 ` [PATCH v1 3/5] cmd: nvme: Add flush support dmukhin 2026-05-28 9:29 ` Neil Armstrong 2026-05-29 3:36 ` dmukhin 2026-05-28 1:20 ` [PATCH v1 4/5] drivers: nvme: Export nvme_shutdown symbol dmukhin 2026-05-28 1:20 ` [PATCH v1 5/5] docs: nvme: Update QEMU command for testing dmukhin
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.