@@ -2015,21 +2015,51 @@ static void nvme_configure_metadata(struct nvme_ctrl *ctrl,
20152015}
20162016
20172017
2018- static void nvme_update_atomic_write_disk_info (struct nvme_ns * ns ,
2019- struct nvme_id_ns * id , struct queue_limits * lim ,
2020- u32 bs , u32 atomic_bs )
2018+ static u32 nvme_configure_atomic_write (struct nvme_ns * ns ,
2019+ struct nvme_id_ns * id , struct queue_limits * lim , u32 bs )
20212020{
2022- unsigned int boundary = 0 ;
2021+ u32 atomic_bs , boundary = 0 ;
20232022
2024- if (id -> nsfeat & NVME_NS_FEAT_ATOMICS && id -> nawupf ) {
2025- if (le16_to_cpu (id -> nabspf ))
2023+ /*
2024+ * We do not support an offset for the atomic boundaries.
2025+ */
2026+ if (id -> nabo )
2027+ return bs ;
2028+
2029+ if ((id -> nsfeat & NVME_NS_FEAT_ATOMICS ) && id -> nawupf ) {
2030+ /*
2031+ * Use the per-namespace atomic write unit when available.
2032+ */
2033+ atomic_bs = (1 + le16_to_cpu (id -> nawupf )) * bs ;
2034+ if (id -> nabspf )
20262035 boundary = (le16_to_cpu (id -> nabspf ) + 1 ) * bs ;
2036+ } else {
2037+ /*
2038+ * Use the controller wide atomic write unit. This sucks
2039+ * because the limit is defined in terms of logical blocks while
2040+ * namespaces can have different formats, and because there is
2041+ * no clear language in the specification prohibiting different
2042+ * values for different controllers in the subsystem.
2043+ */
2044+ atomic_bs = (1 + ns -> ctrl -> awupf ) * bs ;
2045+ }
2046+
2047+ if (!ns -> ctrl -> subsys -> atomic_bs ) {
2048+ ns -> ctrl -> subsys -> atomic_bs = atomic_bs ;
2049+ } else if (ns -> ctrl -> subsys -> atomic_bs != atomic_bs ) {
2050+ dev_err_ratelimited (ns -> ctrl -> device ,
2051+ "%s: Inconsistent Atomic Write Size, Namespace will not be added: Subsystem=%d bytes, Controller/Namespace=%d bytes\n" ,
2052+ ns -> disk ? ns -> disk -> disk_name : "?" ,
2053+ ns -> ctrl -> subsys -> atomic_bs ,
2054+ atomic_bs );
20272055 }
2056+
20282057 lim -> atomic_write_hw_max = atomic_bs ;
20292058 lim -> atomic_write_hw_boundary = boundary ;
20302059 lim -> atomic_write_hw_unit_min = bs ;
20312060 lim -> atomic_write_hw_unit_max = rounddown_pow_of_two (atomic_bs );
20322061 lim -> features |= BLK_FEAT_ATOMIC_WRITES ;
2062+ return atomic_bs ;
20332063}
20342064
20352065static u32 nvme_max_drv_segments (struct nvme_ctrl * ctrl )
@@ -2067,34 +2097,8 @@ static bool nvme_update_disk_info(struct nvme_ns *ns, struct nvme_id_ns *id,
20672097 valid = false;
20682098 }
20692099
2070- atomic_bs = phys_bs = bs ;
2071- if (id -> nabo == 0 ) {
2072- /*
2073- * Bit 1 indicates whether NAWUPF is defined for this namespace
2074- * and whether it should be used instead of AWUPF. If NAWUPF ==
2075- * 0 then AWUPF must be used instead.
2076- */
2077- if (id -> nsfeat & NVME_NS_FEAT_ATOMICS && id -> nawupf )
2078- atomic_bs = (1 + le16_to_cpu (id -> nawupf )) * bs ;
2079- else
2080- atomic_bs = (1 + ns -> ctrl -> awupf ) * bs ;
2081-
2082- /*
2083- * Set subsystem atomic bs.
2084- */
2085- if (ns -> ctrl -> subsys -> atomic_bs ) {
2086- if (atomic_bs != ns -> ctrl -> subsys -> atomic_bs ) {
2087- dev_err_ratelimited (ns -> ctrl -> device ,
2088- "%s: Inconsistent Atomic Write Size, Namespace will not be added: Subsystem=%d bytes, Controller/Namespace=%d bytes\n" ,
2089- ns -> disk ? ns -> disk -> disk_name : "?" ,
2090- ns -> ctrl -> subsys -> atomic_bs ,
2091- atomic_bs );
2092- }
2093- } else
2094- ns -> ctrl -> subsys -> atomic_bs = atomic_bs ;
2095-
2096- nvme_update_atomic_write_disk_info (ns , id , lim , bs , atomic_bs );
2097- }
2100+ phys_bs = bs ;
2101+ atomic_bs = nvme_configure_atomic_write (ns , id , lim , bs );
20982102
20992103 if (id -> nsfeat & NVME_NS_FEAT_IO_OPT ) {
21002104 /* NPWG = Namespace Preferred Write Granularity */
0 commit comments