Page MenuHomeFreeBSD

D58821.diff
No OneTemporary

D58821.diff

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
@@ -45,6 +45,8 @@
#include <vm/vm_extern.h>
#include <vm/vm_map.h>
+#include <dev/pci/pcivar.h>
+
#include "nvme_private.h"
#include "nvme_linux.h"
@@ -192,6 +194,8 @@
if (ctrlr->quirks & QUIRK_APPLE_SHARED_CID_SPACE)
num_trackers = min(num_trackers,
NVME_ADMIN_ENTRIES - ctrlr->adminq.num_trackers);
+ if (ctrlr->quirks & QUIRK_APPLE_S3X_SERIALIZE)
+ num_trackers = 1;
/*
* Our best estimate for the maximum number of I/Os that we should
@@ -199,7 +203,8 @@
* not a hard limit and will need to be revisited when the upper layers
* of the storage system grows multi-queue support.
*/
- ctrlr->max_hw_pend_io = num_trackers * ctrlr->num_io_queues * 3 / 4;
+ ctrlr->max_hw_pend_io = max(1,
+ num_trackers * ctrlr->num_io_queues * 3 / 4);
ctrlr->ioq = malloc(ctrlr->num_io_queues * sizeof(struct nvme_qpair),
M_NVME, M_ZERO | M_WAITOK);
@@ -391,7 +396,7 @@
cc |= NVMEF(NVME_CC_REG_CSS, 0);
cc |= NVMEF(NVME_CC_REG_AMS, 0);
cc |= NVMEF(NVME_CC_REG_SHN, 0);
- cc |= NVMEF(NVME_CC_REG_IOSQES, 6); /* SQ entry size == 64 == 2^6 */
+ cc |= NVMEF(NVME_CC_REG_IOSQES, ctrlr->io_sqes);
cc |= NVMEF(NVME_CC_REG_IOCQES, 4); /* CQ entry size == 16 == 2^4 */
/*
@@ -424,9 +429,28 @@
}
}
+static int
+nvme_ctrlr_pcie_flr(struct nvme_controller *ctrlr, uint32_t csts)
+{
+ nvme_printf(ctrlr,
+ "fatal status; attempting PCIe function level reset\n");
+ pci_save_state(ctrlr->dev);
+ if (!pcie_flr(ctrlr->dev, 1000, true)) {
+ pci_restore_state(ctrlr->dev);
+ nvme_printf(ctrlr, "PCIe function level reset failed\n");
+ nvme_ctrlr_devctl(ctrlr, "FLR_FAILED", "csts=0x%08x", csts);
+ return (ENXIO);
+ }
+ pci_restore_state(ctrlr->dev);
+ nvme_printf(ctrlr, "PCIe function level reset completed\n");
+ nvme_ctrlr_devctl(ctrlr, "FLR_COMPLETED", "csts=0x%08x", csts);
+ return (0);
+}
+
static int
nvme_ctrlr_hw_reset(struct nvme_controller *ctrlr)
{
+ uint32_t csts;
int err;
TSENTER();
@@ -434,6 +458,14 @@
ctrlr->is_failed_admin = true;
nvme_ctrlr_disable_qpairs(ctrlr);
+ csts = nvme_mmio_read_4(ctrlr, csts);
+ if ((ctrlr->quirks & QUIRK_PCIE_FLR_ON_FATAL) != 0 &&
+ csts != NVME_GONE && NVMEV(NVME_CSTS_REG_CFS, csts) != 0) {
+ err = nvme_ctrlr_pcie_flr(ctrlr, csts);
+ if (err != 0)
+ goto out;
+ }
+
err = nvme_ctrlr_disable(ctrlr);
if (err != 0)
goto out;
@@ -490,6 +522,8 @@
ctrlr->max_xfer_size = min(ctrlr->max_xfer_size,
1 << (ctrlr->cdata.mdts + NVME_MPS_SHIFT +
NVME_CAP_HI_MPSMIN(ctrlr->cap_hi)));
+ if (ctrlr->quirks & QUIRK_APPLE_S3X_SERIALIZE)
+ ctrlr->max_xfer_size = min(ctrlr->max_xfer_size, 8192U);
return (0);
}
@@ -1653,6 +1687,9 @@
int status, timeout_period;
ctrlr->dev = dev;
+ ctrlr->io_sqes =
+ (ctrlr->quirks & QUIRK_APPLE_128_BYTE_SQES) != 0 ?
+ NVME_IOSQES_128 : NVME_IOSQES_64;
mtx_init(&ctrlr->lock, "nvme ctrlr lock", NULL, MTX_DEF);
if (bus_get_domain(dev, &ctrlr->domain) != 0)
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
@@ -97,10 +97,13 @@
{ 0xa821144d, 0, 0, "Samsung PM1725", QUIRK_DELAY_B4_CHK_RDY },
{ 0xa822144d, 0, 0, "Samsung PM1725a", QUIRK_DELAY_B4_CHK_RDY },
{ 0x07f015ad, 0, 0, "VMware NVMe Controller" },
- { 0x2003106b, 0, 0, "Apple S3X NVMe Controller" },
+ { 0x2003106b, 0, 0, "Apple S3X NVMe Controller",
+ QUIRK_APPLE_NO_ASYNC_EVENT | QUIRK_PCIE_FLR_ON_FATAL |
+ QUIRK_APPLE_S3X_SERIALIZE },
{ 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_NO_ASYNC_EVENT | QUIRK_APPLE_SINGLE_VECTOR |
+ QUIRK_APPLE_128_BYTE_SQES },
{ 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
@@ -165,7 +165,7 @@
uint32_t num_entries;
uint32_t num_trackers;
- uint32_t sqe_shift; /* SQE size shift: sqes_max - 6; 0 = 64 bytes, 1 = 128 bytes */
+ uint32_t sqe_shift;
uint16_t cid_base; /* CID offset for SHARED_TAGS IO queues */
uint32_t sq_tdbl_off;
uint32_t cq_hdbl_off;
@@ -223,6 +223,7 @@
uint32_t ready_timeout_in_ms;
uint32_t quirks;
uint8_t max_identify_cns; /* max CNS value for IDENTIFY (0 = no limit) */
+ uint8_t io_sqes;
#define QUIRK_DELAY_B4_CHK_RDY 1 /* Can't touch MMIO on disable */
#define QUIRK_DISABLE_TIMEOUT 2 /* Disable broken completion timeout feature */
#define QUIRK_INTEL_ALIGNMENT 4 /* Pre NVMe 1.3 performance alignment */
@@ -233,6 +234,13 @@
#define QUIRK_APPLE_NO_ASYNC_EVENT 0x40 /* Skip NVMe async event requests */
#define QUIRK_APPLE_SINGLE_VECTOR 0x80 /* Single MSI vector, one IO queue */
#define QUIRK_EMPTY_NAMESPACE_CHANGED_LOG 0x100 /* Change Namespace List Log is always empty */
+#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 */
+
+/* Values programmed into CC.IOSQES (log2 of the SQE size in bytes). */
+#define NVME_IOSQES_64 6
+#define NVME_IOSQES_128 7
int resource_id;
struct resource *resource;
@@ -333,7 +341,7 @@
/*
* Access the idx'th submission queue entry.
- * sqe_shift is sqes_max - 6: 0 for standard 64-byte SQEs, 1 for 128-byte.
+ * sqe_shift is 0 for standard 64-byte SQEs and 1 for 128-byte SQEs.
*/
#define NVME_SQE(qpair, idx) (&(qpair)->cmd[(idx) << (qpair)->sqe_shift])
diff --git a/sys/dev/nvme/nvme_qpair.c b/sys/dev/nvme/nvme_qpair.c
--- a/sys/dev/nvme/nvme_qpair.c
+++ b/sys/dev/nvme/nvme_qpair.c
@@ -531,13 +531,12 @@
qpair->num_trackers = num_trackers;
qpair->ctrlr = ctrlr;
- /* sqes[7:4]: max SQE size exponent; admin always 64 bytes per spec. */
- if (qpair->id != 0) {
- uint8_t sqes_max = (ctrlr->cdata.sqes >> 4) & 0xf;
- qpair->sqe_shift = (sqes_max > 6) ? (sqes_max - 6) : 0;
- } else {
- qpair->sqe_shift = 0;
- }
+ KASSERT(ctrlr->io_sqes == NVME_IOSQES_64 ||
+ ctrlr->io_sqes == NVME_IOSQES_128,
+ ("invalid CC.IOSQES value %u", ctrlr->io_sqes));
+ /* Admin SQEs are always 64 bytes. */
+ qpair->sqe_shift = qpair->id == 0 ? 0 :
+ ctrlr->io_sqes - NVME_IOSQES_64;
if ((ctrlr->quirks & QUIRK_APPLE_SHARED_CID_SPACE) && qpair->id != 0)
qpair->cid_base = ctrlr->adminq.num_trackers;
else

File Metadata

Mime Type
text/plain
Expires
Mon, Sep 14, 12:58 AM (17 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38879453
Default Alt Text
D58821.diff (6 KB)

Event Timeline