Since NVM Command Spec 1.1, OPTPERF comprises both bits 4 and 5 of
NSFEAT in the Identify Namespace structure. Replace NVME_NS_FEAT_IO_OPT,
which represented only bit 4, with NVME_NS_FEAT_OPTPERF_SHIFT and
NVME_NS_FEAT_OPTPERF_MASK.
Update nvme_update_disk_info() to check both OPTPERF bits, as NPWG and
NOWS are supported even if only bit 5 is set.
Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
---
drivers/nvme/host/core.c | 3 ++-
include/linux/nvme.h | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 3a2126584a23..674dd823b209 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -2095,11 +2095,12 @@ static bool nvme_update_disk_info(struct nvme_ns *ns, struct nvme_id_ns *id,
}
phys_bs = bs;
atomic_bs = nvme_configure_atomic_write(ns, id, lim, bs);
- if (id->nsfeat & NVME_NS_FEAT_IO_OPT) {
+ if (id->nsfeat >> NVME_NS_FEAT_OPTPERF_SHIFT &
+ NVME_NS_FEAT_OPTPERF_MASK) {
/* NPWG = Namespace Preferred Write Granularity */
phys_bs = bs * (1 + le16_to_cpu(id->npwg));
/* NOWS = Namespace Optimal Write Size */
if (id->nows)
io_opt = bs * (1 + le16_to_cpu(id->nows));
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index bc991d4ae89d..f279e5d72e2d 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -593,11 +593,12 @@ enum {
};
enum {
NVME_NS_FEAT_THIN = 1 << 0,
NVME_NS_FEAT_ATOMICS = 1 << 1,
- NVME_NS_FEAT_IO_OPT = 1 << 4,
+ NVME_NS_FEAT_OPTPERF_SHIFT = 4,
+ NVME_NS_FEAT_OPTPERF_MASK = 0x3,
NVME_NS_ATTR_RO = 1 << 0,
NVME_NS_FLBAS_LBA_MASK = 0xf,
NVME_NS_FLBAS_LBA_UMASK = 0x60,
NVME_NS_FLBAS_LBA_SHIFT = 1,
NVME_NS_FLBAS_META_EXT = 0x10,
--
2.45.2
On Thu, Feb 19, 2026 at 08:28:05PM -0700, Caleb Sander Mateos wrote: > Since NVM Command Spec 1.1, OPTPERF comprises both bits 4 and 5 of > NSFEAT in the Identify Namespace structure. Replace NVME_NS_FEAT_IO_OPT, > which represented only bit 4, with NVME_NS_FEAT_OPTPERF_SHIFT and > NVME_NS_FEAT_OPTPERF_MASK. As you're deeper in this than me: do the older specs require the other bit to be cleared to zero and this is all compatible? Or do we need to guard it somehow? Otherwise looks good.
On Fri, Feb 20, 2026 at 8:07 AM Christoph Hellwig <hch@lst.de> wrote: > > On Thu, Feb 19, 2026 at 08:28:05PM -0700, Caleb Sander Mateos wrote: > > Since NVM Command Spec 1.1, OPTPERF comprises both bits 4 and 5 of > > NSFEAT in the Identify Namespace structure. Replace NVME_NS_FEAT_IO_OPT, > > which represented only bit 4, with NVME_NS_FEAT_OPTPERF_SHIFT and > > NVME_NS_FEAT_OPTPERF_MASK. > > As you're deeper in this than me: do the older specs require the > other bit to be cleared to zero and this is all compatible? Or do > we need to guard it somehow? In NVM Command Set spec 1.0 (NVMe version 2.0), OPTPERF is only bit 4 of NSFEAT and the higher bits are reserved. I think it seems relatively safe to assume bit 5 will be reported as 0 on controllers advertising older NVMe versions, but you're correct that the host should technically check for version >= 2.1 before using bit 5. Let me know which approach you'd prefer. Thanks, Caleb
On Fri, Feb 20, 2026 at 08:17:29AM -0800, Caleb Sander Mateos wrote: > On Fri, Feb 20, 2026 at 8:07 AM Christoph Hellwig <hch@lst.de> wrote: > > > > On Thu, Feb 19, 2026 at 08:28:05PM -0700, Caleb Sander Mateos wrote: > > > Since NVM Command Spec 1.1, OPTPERF comprises both bits 4 and 5 of > > > NSFEAT in the Identify Namespace structure. Replace NVME_NS_FEAT_IO_OPT, > > > which represented only bit 4, with NVME_NS_FEAT_OPTPERF_SHIFT and > > > NVME_NS_FEAT_OPTPERF_MASK. > > > > As you're deeper in this than me: do the older specs require the > > other bit to be cleared to zero and this is all compatible? Or do > > we need to guard it somehow? > > In NVM Command Set spec 1.0 (NVMe version 2.0), OPTPERF is only bit 4 > of NSFEAT and the higher bits are reserved. I think it seems > relatively safe to assume bit 5 will be reported as 0 on controllers > advertising older NVMe versions, but you're correct that the host > should technically check for version >= 2.1 before using bit 5. Let me > know which approach you'd prefer. Not entirely sure, but either way the code should have a big fat comment about this.
© 2016 - 2026 Red Hat, Inc.