]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
nvme: stop using AWUPF
authorJohn Garry <john.g.garry@oracle.com>
Wed, 28 Jan 2026 08:26:23 +0000 (08:26 +0000)
committerKeith Busch <kbusch@kernel.org>
Wed, 28 Jan 2026 15:02:38 +0000 (07:02 -0800)
As described at [0], much of the atomic write parts of the specification
are lacking.

For now, there is nothing which we can do in software about the lack of
a dedicated NVMe write atomic command.

As for reading the atomic write limits, it is felt that the per-namespace
values are mostly properly specified and it is assumed that they are
properly implemented.

The specification of NAWUPF is quite clear. However the specification of
NABSPF is less clear. The lack of clarity in NABSPF comes from deciding
whether NABSPF applies when NSABP is 0 - it is assumed that NSABPF does
not apply when NSABP is 0.

As for the per-controller AWUPF, how this value applies to shared
namespaces is missing in the specification. Furthermore, the value is in
terms of logical blocks, which is an NS entity.

Since AWUPF is so poorly defined, stop using it already together.
Hopefully this will force vendors to implement NAWUPF support always.

Note that AWUPF not only effects atomic write support, but also the
physical block size reported for the device.

To help users know this restriction, log an info message per NS.

[0] https://lore.kernel.org/linux-nvme/20250707141834.GA30198@lst.de/

Tested-by: Nilay Shroff <nilay@linux.ibm.com>
Reviewed-by: Nilay Shroff <nilay@linux.ibm.com>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: John Garry <john.g.garry@oracle.com>
Signed-off-by: Keith Busch <kbusch@kernel.org>
drivers/nvme/host/core.c
drivers/nvme/host/nvme.h

index 7bf228df6001f1f4d0b3c570de285a5eb17bb08e..83efc88ac0f988dbb38084d971af7fd7a2353d9e 100644 (file)
@@ -2045,14 +2045,10 @@ static u32 nvme_configure_atomic_write(struct nvme_ns *ns,
                if (id->nabspf)
                        boundary = (le16_to_cpu(id->nabspf) + 1) * bs;
        } else {
-               /*
-                * Use the controller wide atomic write unit.  This sucks
-                * because the limit is defined in terms of logical blocks while
-                * namespaces can have different formats, and because there is
-                * no clear language in the specification prohibiting different
-                * values for different controllers in the subsystem.
-                */
-               atomic_bs = (1 + ns->ctrl->subsys->awupf) * bs;
+               if (ns->ctrl->awupf)
+                       dev_info_once(ns->ctrl->device,
+                               "AWUPF ignored, only NAWUPF accepted\n");
+               atomic_bs = bs;
        }
 
        lim->atomic_write_hw_max = atomic_bs;
@@ -3221,7 +3217,6 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
        memcpy(subsys->model, id->mn, sizeof(subsys->model));
        subsys->vendor_id = le16_to_cpu(id->vid);
        subsys->cmic = id->cmic;
-       subsys->awupf = le16_to_cpu(id->awupf);
 
        /* Versions prior to 1.4 don't necessarily report a valid type */
        if (id->cntrltype == NVME_CTRL_DISC ||
@@ -3654,6 +3649,7 @@ static int nvme_init_identify(struct nvme_ctrl *ctrl)
                dev_pm_qos_expose_latency_tolerance(ctrl->device);
        else if (!ctrl->apst_enabled && prev_apst_enabled)
                dev_pm_qos_hide_latency_tolerance(ctrl->device);
+       ctrl->awupf = le16_to_cpu(id->awupf);
 out_free:
        kfree(id);
        return ret;
index 523015ae2add7a6a9369fc5cd9fa6126575afded..9971045dbc05e9bb9d7fa32ad540fd107d8c8b83 100644 (file)
@@ -464,6 +464,8 @@ struct nvme_ctrl {
 
        enum nvme_ctrl_type cntrltype;
        enum nvme_dctype dctype;
+
+       u16                     awupf; /* 0's based value. */
 };
 
 static inline enum nvme_ctrl_state nvme_ctrl_state(struct nvme_ctrl *ctrl)
@@ -496,7 +498,6 @@ struct nvme_subsystem {
        u8                      cmic;
        enum nvme_subsys_type   subtype;
        u16                     vendor_id;
-       u16                     awupf; /* 0's based value. */
        struct ida              ns_ida;
 #ifdef CONFIG_NVME_MULTIPATH
        enum nvme_iopolicy      iopolicy;