diff options
| author | Abdelkader Boudih <seuros@FreeBSD.org> | 2026-09-24 14:19:51 +0000 |
|---|---|---|
| committer | Abdelkader Boudih <seuros@FreeBSD.org> | 2026-09-24 14:19:51 +0000 |
| commit | 2c41f7d8a034ee64a0aaa69a1aa5cb07748a1a32 (patch) | |
| tree | ee278bfad21c3ece262878eeac4c320458dbc94f /sys | |
| parent | b5d1e0c5a4929e2be3bc58aad8e5b707860ec0fd (diff) | |
nvme: honor FLBAS Format Index Upper when selecting the LBA format
Added nvme_ns_data_format_index() in the nvme, nda, and nvmf
host paths as well as nvmecontrol and camdd.
Reviewed by: imp, adrian
Differential Revision: https://reviews.freebsd.org/D59627
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/cam/nvme/nvme_da.c | 2 | ||||
| -rw-r--r-- | sys/dev/nvme/nvme.h | 18 | ||||
| -rw-r--r-- | sys/dev/nvme/nvme_ns.c | 4 | ||||
| -rw-r--r-- | sys/dev/nvmf/host/nvmf_ns.c | 4 |
4 files changed, 23 insertions, 5 deletions
diff --git a/sys/cam/nvme/nvme_da.c b/sys/cam/nvme/nvme_da.c index 31bb7c4b7d3c..e1831331f8f3 100644 --- a/sys/cam/nvme/nvme_da.c +++ b/sys/cam/nvme/nvme_da.c @@ -310,7 +310,7 @@ ndasetgeom(struct nda_softc *softc, struct cam_periph *periph) */ flags = disk->d_flags & DISKFLAG_UNMAPPED_BIO; /* Need to preserve */ - flbas_fmt = NVMEV(NVME_NS_DATA_FLBAS_FORMAT, nsd->flbas); + flbas_fmt = nvme_ns_data_format_index(nsd); lbads = NVMEV(NVME_NS_DATA_LBAF_LBADS, nsd->lbaf[flbas_fmt]); disk->d_sectorsize = 1 << lbads; disk->d_mediasize = (off_t)(disk->d_sectorsize * nsd->nsze); diff --git a/sys/dev/nvme/nvme.h b/sys/dev/nvme/nvme.h index b7e82e83a13f..25e2bd67f258 100644 --- a/sys/dev/nvme/nvme.h +++ b/sys/dev/nvme/nvme.h @@ -559,6 +559,11 @@ enum nvme_psdt { #define NVME_NS_DATA_FLBAS_FORMAT_MASK (0xF) #define NVME_NS_DATA_FLBAS_EXTENDED_SHIFT (4) #define NVME_NS_DATA_FLBAS_EXTENDED_MASK (0x1) +#define NVME_NS_DATA_FLBAS_FORMAT_MSB_SHIFT (5) +#define NVME_NS_DATA_FLBAS_FORMAT_MSB_MASK (0x3) +/* FIDXL width, and the format count below which FIDXU is reserved. */ +#define NVME_NS_DATA_FLBAS_FIDXL_BITS (4) +#define NVME_NS_DATA_LBAF_BASE_COUNT (16) /** metadata capabilities */ /* metadata can be transferred as part of data prp list */ @@ -2083,6 +2088,19 @@ extern int nvme_use_nvd; #endif /* _KERNEL */ +static inline uint8_t +nvme_ns_data_format_index(const struct nvme_namespace_data *nsdata) +{ + uint8_t fmt; + + fmt = NVMEV(NVME_NS_DATA_FLBAS_FORMAT, nsdata->flbas); + /* FIDXU is valid only above the base count; NLBAF is 0's based. */ + if (nsdata->nlbaf + 1 > NVME_NS_DATA_LBAF_BASE_COUNT) + fmt |= NVMEV(NVME_NS_DATA_FLBAS_FORMAT_MSB, nsdata->flbas) << + NVME_NS_DATA_FLBAS_FIDXL_BITS; + return (fmt); +} + /* Endianess conversion functions for NVMe structs */ static inline void nvme_completion_swapbytes(struct nvme_completion *s __unused) diff --git a/sys/dev/nvme/nvme_ns.c b/sys/dev/nvme/nvme_ns.c index f52e75bfa243..1124aaa4cad9 100644 --- a/sys/dev/nvme/nvme_ns.c +++ b/sys/dev/nvme/nvme_ns.c @@ -192,7 +192,7 @@ nvme_ns_get_sector_size(struct nvme_namespace *ns) { uint8_t flbas_fmt, lbads; - flbas_fmt = NVMEV(NVME_NS_DATA_FLBAS_FORMAT, ns->data.flbas); + flbas_fmt = nvme_ns_data_format_index(&ns->data); lbads = NVMEV(NVME_NS_DATA_LBAF_LBADS, ns->data.lbaf[flbas_fmt]); return (1 << lbads); @@ -568,7 +568,7 @@ nvme_ns_construct(struct nvme_namespace *ns, uint32_t id, * Check the validity of the format specified. Note: format is a 0-based * value, so > is appropriate here, not >=. */ - flbas_fmt = NVMEV(NVME_NS_DATA_FLBAS_FORMAT, ns->data.flbas); + flbas_fmt = nvme_ns_data_format_index(&ns->data); if (flbas_fmt > ns->data.nlbaf) { nvme_printf(ctrlr, "nsid %d lba format %d invalid (> %d)\n", id, flbas_fmt, ns->data.nlbaf + 1); diff --git a/sys/dev/nvmf/host/nvmf_ns.c b/sys/dev/nvmf/host/nvmf_ns.c index d57280e19d41..572649870e05 100644 --- a/sys/dev/nvmf/host/nvmf_ns.c +++ b/sys/dev/nvmf/host/nvmf_ns.c @@ -353,7 +353,7 @@ nvmf_init_ns(struct nvmf_softc *sc, uint32_t id, goto fail; } - lbaf = NVMEV(NVME_NS_DATA_FLBAS_FORMAT, data->flbas); + lbaf = nvme_ns_data_format_index(data); if (lbaf > data->nlbaf) { ns_printf(ns, "Invalid LBA format index\n"); goto fail; @@ -505,7 +505,7 @@ nvmf_update_ns(struct nvmf_namespace *ns, return (false); } - lbaf = NVMEV(NVME_NS_DATA_FLBAS_FORMAT, data->flbas); + lbaf = nvme_ns_data_format_index(data); if (lbaf > data->nlbaf) { ns_printf(ns, "Invalid LBA format index\n"); return (false); |
