From: Shao Mingyin nvme_query_fdp_info() passes a struct nvme_fdp_config, which is exactly four bytes, as the result buffer of nvme_get_features(): struct nvme_fdp_config fdp; ret = nvme_get_features(ctrl, NVME_FEAT_FDP, info->endgid, NULL, 0, &fdp); if (!(fdp.flags & FDPCFG_FDPE)) return 0; ret = nvme_query_fdp_granularity(ctrl, info, fdp.fdpcidx); nvme_features() stores the result with *result = le32_to_cpu(res.u32); i.e. it writes a CPU-endian dword through the pointer. On a big-endian host this puts the flags byte in the fourth byte of the structure, so fdp.flags is always zero and FDP support is silently disabled, while fdpcidx would be read from the wrong byte. Read the result as a u32 and decode the flags and the FDP config index explicitly, which works on both endiannesses. Fixes: 30b5f20bb2dd ("nvme: register fdp parameters with the block layer") Cc: stable@vger.kernel.org Signed-off-by: Shao Mingyin --- Tested on 7.3.0-next-20261030 under QEMU/TCG (guest s390x, big-endian), loop transport + file-backed namespace. The nvmet target needs no FDP hardware: a TEST-ONLY stub (applied to both kernels) advertises FDPS and answers the FDP Get Features / configs log / RUHS commands; the only difference between the two kernels is this patch. The FDP probe runs during namespace scan; the verdict is /sys/block/nvme0n1/queue/max_write_streams (= nr_plids): unpatched (big-endian): max_write_streams=0 FDP silently disabled patched (big-endian): max_write_streams=1 FDP registered On x86 (little-endian) both kernels report max_write_streams=1, i.e. no regression. drivers/nvme/host/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index a7a4d09644c1..45feafa00325 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -2339,8 +2339,8 @@ static int nvme_query_fdp_info(struct nvme_ns *ns, struct nvme_ns_info *info) struct nvme_ns_head *head = ns->head; struct nvme_ctrl *ctrl = ns->ctrl; struct nvme_fdp_ruh_status *ruhs; - struct nvme_fdp_config fdp; struct nvme_command c = {}; + u32 fdp; size_t size; int i, ret; @@ -2351,10 +2351,10 @@ static int nvme_query_fdp_info(struct nvme_ns *ns, struct nvme_ns_info *info) return ret; } - if (!(fdp.flags & FDPCFG_FDPE)) + if (!(fdp & FDPCFG_FDPE)) return 0; - ret = nvme_query_fdp_granularity(ctrl, info, fdp.fdpcidx); + ret = nvme_query_fdp_granularity(ctrl, info, (fdp >> 8) & 0xff); if (!info->runs) return ret; -- 2.43.0