Page MenuHomeFreeBSD

D59155.diff
No OneTemporary

D59155.diff

diff --git a/share/man/man4/nvme.4 b/share/man/man4/nvme.4
--- a/share/man/man4/nvme.4
+++ b/share/man/man4/nvme.4
@@ -31,7 +31,7 @@
.\"
.\" Author: Jim Harris <jimharris@FreeBSD.org>
.\"
-.Dd August 27, 2026
+.Dd September 1, 2026
.Dt NVME 4
.Os
.Sh NAME
@@ -48,6 +48,7 @@
.Cd hw.nvme.min_cpus_per_ioq= Ns Aq Ar X
.Cd hw.nvme.force_intx= Ns Ar 1
.Cd hw.nvme.hmb_max
+.Cd hw.nvme.arb_burst= Ns Aq Ar X
.Cd hw.nvme.apst_enable= Ns Ar 1
.Cd hw.nvme.apst_data
.Cd hw.nvme.use_nvd= Ns Ar 0
@@ -166,6 +167,12 @@
Control maximum amount of system RAM in bytes
to use as Host Memory Buffer for capable devices.
The default value is 5% of physical memory size per device.
+.It Va hw.nvme.arb_burst=X
+Override the arbitration burst,
+which is otherwise programmed from the controller's recommendation
+when it publishes one.
+Values 0 through 6 request a burst of 2^X commands and 7 requests no
+limit; -1, the default, follows the controller's recommendation.
.It Va hw.nvme.apst_enable=1
Enable Autonomous Power State Transition
.Pq APST .
diff --git a/sys/dev/nvme/nvme.h b/sys/dev/nvme/nvme.h
--- a/sys/dev/nvme/nvme.h
+++ b/sys/dev/nvme/nvme.h
@@ -249,6 +249,17 @@
#define NVME_QPRIO_MEDIUM (2)
#define NVME_QPRIO_LOW (3)
+/* Arbitration feature, cdw11 */
+#define NVME_ARB_AB_SHIFT (0)
+#define NVME_ARB_AB_MASK (0x7)
+#define NVME_ARB_AB_NO_LIMIT (0x7)
+#define NVME_ARB_LPW_SHIFT (8)
+#define NVME_ARB_LPW_MASK (0xFF)
+#define NVME_ARB_MPW_SHIFT (16)
+#define NVME_ARB_MPW_MASK (0xFF)
+#define NVME_ARB_HPW_SHIFT (24)
+#define NVME_ARB_HPW_MASK (0xFF)
+
#define NVME_STATUS_P_SHIFT (0)
#define NVME_STATUS_P_MASK (0x1)
#define NVME_STATUS_SC_SHIFT (1)
diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c
--- a/sys/dev/nvme/nvme_ctrlr.c
+++ b/sys/dev/nvme/nvme_ctrlr.c
@@ -876,6 +876,43 @@
free(data, M_NVME);
}
+static void
+nvme_ctrlr_arbitration_done(void *arg, const struct nvme_completion *cpl)
+{
+ struct nvme_controller *ctrlr = arg;
+
+ if (nvme_completion_is_error(cpl))
+ nvme_printf(ctrlr, "setting arbitration burst failed\n");
+}
+
+static void
+nvme_ctrlr_configure_arbitration(struct nvme_controller *ctrlr)
+{
+ int burst;
+
+ burst = -1;
+ TUNABLE_INT_FETCH("hw.nvme.arb_burst", &burst);
+ if (burst < -1 || burst > NVME_ARB_AB_NO_LIMIT) {
+ nvme_printf(ctrlr, "invalid hw.nvme.arb_burst=%d specified\n",
+ burst);
+ burst = -1;
+ }
+
+ if (burst == -1) {
+ if (ctrlr->cdata.rab == 0 ||
+ (ctrlr->quirks & QUIRK_IGNORE_RAB) != 0)
+ return;
+ burst = min(ctrlr->cdata.rab, NVME_ARB_AB_NO_LIMIT);
+ } else if ((ctrlr->quirks & QUIRK_IGNORE_RAB) != 0) {
+ nvme_printf(ctrlr,
+ "forcing arbitration burst %d despite controller quirk\n",
+ burst);
+ }
+
+ nvme_ctrlr_cmd_set_arbitration(ctrlr, NVMEF(NVME_ARB_AB, burst),
+ nvme_ctrlr_arbitration_done, ctrlr);
+}
+
static void
nvme_ctrlr_configure_int_coalescing(struct nvme_controller *ctrlr)
{
@@ -1143,6 +1180,7 @@
nvme_ctrlr_configure_aer(ctrlr);
nvme_ctrlr_configure_apst(ctrlr);
+ nvme_ctrlr_configure_arbitration(ctrlr);
nvme_ctrlr_configure_int_coalescing(ctrlr);
for (i = 0; i < ctrlr->num_io_queues; i++)
diff --git a/sys/dev/nvme/nvme_ctrlr_cmd.c b/sys/dev/nvme/nvme_ctrlr_cmd.c
--- a/sys/dev/nvme/nvme_ctrlr_cmd.c
+++ b/sys/dev/nvme/nvme_ctrlr_cmd.c
@@ -260,6 +260,15 @@
0, 0, 0, 0, NULL, 0, cb_fn, cb_arg);
}
+void
+nvme_ctrlr_cmd_set_arbitration(struct nvme_controller *ctrlr,
+ uint32_t cdw11, nvme_cb_fn_t cb_fn, void *cb_arg)
+{
+
+ nvme_ctrlr_cmd_set_feature(ctrlr, NVME_FEAT_ARBITRATION, cdw11,
+ 0, 0, 0, 0, NULL, 0, cb_fn, cb_arg);
+}
+
void
nvme_ctrlr_cmd_get_log_page(struct nvme_controller *ctrlr, uint8_t log_page,
uint32_t nsid, void *payload, uint32_t payload_size, nvme_cb_fn_t cb_fn,
diff --git a/sys/dev/nvme/nvme_pci.c b/sys/dev/nvme/nvme_pci.c
--- a/sys/dev/nvme/nvme_pci.c
+++ b/sys/dev/nvme/nvme_pci.c
@@ -99,11 +99,12 @@
{ 0x07f015ad, 0, 0, "VMware NVMe Controller" },
{ 0x2003106b, 0, 0, "Apple S3X NVMe Controller",
QUIRK_APPLE_NO_ASYNC_EVENT | QUIRK_APPLE_S3X_NS1_ONLY |
- QUIRK_PCIE_FLR_ON_FATAL | QUIRK_APPLE_S3X_SERIALIZE },
+ QUIRK_PCIE_FLR_ON_FATAL | QUIRK_APPLE_S3X_SERIALIZE |
+ QUIRK_IGNORE_RAB },
{ 0x2005106b, 0, 0, "Apple ANS2 NVMe Controller (T2)",
QUIRK_APPLE_IDENTIFY_CNS_BROKEN | QUIRK_APPLE_SHARED_CID_SPACE |
QUIRK_APPLE_NO_ASYNC_EVENT | QUIRK_APPLE_SINGLE_VECTOR |
- QUIRK_APPLE_128_BYTE_SQES },
+ QUIRK_APPLE_128_BYTE_SQES | QUIRK_IGNORE_RAB },
{ 0x80611d0f, 0, 0, "Amazon EBS NVMe Controller",
QUIRK_EMPTY_NAMESPACE_CHANGED_LOG },
{ 0x00000000, 0, 0, NULL }
diff --git a/sys/dev/nvme/nvme_private.h b/sys/dev/nvme/nvme_private.h
--- a/sys/dev/nvme/nvme_private.h
+++ b/sys/dev/nvme/nvme_private.h
@@ -238,6 +238,7 @@
#define QUIRK_APPLE_128_BYTE_SQES 0x400 /* T2 uses 128-byte I/O SQEs */
#define QUIRK_PCIE_FLR_ON_FATAL 0x800 /* Use FLR for a fatal controller */
#define QUIRK_APPLE_S3X_SERIALIZE 0x1000 /* One S3X I/O at a time */
+#define QUIRK_IGNORE_RAB 0x2000 /* Don't configure AB from RAB */
/* Values programmed into CC.IOSQES (log2 of the SQE size in bytes). */
#define NVME_IOSQES_64 6
@@ -396,6 +397,8 @@
uint32_t threshold,
nvme_cb_fn_t cb_fn,
void *cb_arg);
+void nvme_ctrlr_cmd_set_arbitration(struct nvme_controller *ctrlr,
+ uint32_t cdw11, nvme_cb_fn_t cb_fn, void *cb_arg);
void nvme_ctrlr_cmd_get_error_page(struct nvme_controller *ctrlr,
struct nvme_error_information_entry *payload,
uint32_t num_entries, /* 0 = max */

File Metadata

Mime Type
text/plain
Expires
Fri, Sep 4, 10:47 AM (19 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38029680
Default Alt Text
D59155.diff (5 KB)

Event Timeline