Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F171722616
D58821.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D58821.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D58821: nvme: fix Apple S3X controller panic
Attached
Detach File
Event Timeline
Log In to Comment