Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F157547248
D57087.id178274.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D57087.id178274.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
@@ -173,6 +173,18 @@
num_entries = min(num_entries, mqes + 1);
num_entries = min(num_entries, max_entries);
+ /*
+ * Apple T2 ANS2 (SHARED_TAGS): admin and IO queues share a single CID
+ * table in the controller firmware. Admin uses CIDs
+ * 0..adminq.num_trackers-1; IO must use the remainder without
+ * exceeding the table size (NVME_ADMIN_ENTRIES). Cap both num_entries
+ * and num_trackers so that cid_base + num_trackers <= NVME_ADMIN_ENTRIES.
+ */
+ if (ctrlr->quirks & QUIRK_APPLE_SHARED_TAGS) {
+ num_entries = min(num_entries, NVME_ADMIN_ENTRIES);
+ /* Leave room below the table ceiling for the admin CID range. */
+ }
+
num_trackers = NVME_IO_TRACKERS;
TUNABLE_INT_FETCH("hw.nvme.io_trackers", &num_trackers);
@@ -185,6 +197,15 @@
*/
num_trackers = min(num_trackers, (num_entries-1));
+ /*
+ * Apple T2 ANS2: IO CIDs are offset by cid_base (= adminq.num_trackers).
+ * Ensure cid_base + num_trackers <= NVME_ADMIN_ENTRIES so IO CIDs stay
+ * within the controller's shared tag table.
+ */
+ if (ctrlr->quirks & QUIRK_APPLE_SHARED_TAGS)
+ num_trackers = min(num_trackers,
+ NVME_ADMIN_ENTRIES - ctrlr->adminq.num_trackers);
+
/*
* Our best estimate for the maximum number of I/Os that we should
* normally have in flight at one time. This should be viewed as a hint,
@@ -383,7 +404,16 @@
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 */
+ /*
+ * Apple T2 ANS2 uses 128-byte SQ entries (CC.IOSQES = 7).
+ * The T2 appears to ignore CC.IOSQES entirely and always operates
+ * with 128-byte SQEs regardless of what is written here.
+ * We set it anyway for spec compliance.
+ */
+ if (ctrlr->quirks & QUIRK_APPLE_128_BYTES_SQES)
+ cc |= NVMEF(NVME_CC_REG_IOSQES, 7);
+ else
+ cc |= NVMEF(NVME_CC_REG_IOSQES, 6); /* SQ entry size == 64 == 2^6 */
cc |= NVMEF(NVME_CC_REG_IOCQES, 4); /* CQ entry size == 16 == 2^4 */
/*
@@ -749,6 +779,11 @@
struct nvme_async_event_request *aer;
uint32_t i;
+ if (ctrlr->quirks & QUIRK_APPLE_NO_ASYNC_EVENT) {
+ ctrlr->num_aers = 0;
+ return;
+ }
+
ctrlr->async_event_config = NVME_CRIT_WARN_ST_AVAILABLE_SPARE |
NVME_CRIT_WARN_ST_DEVICE_RELIABILITY |
NVME_CRIT_WARN_ST_READ_ONLY |
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
@@ -92,7 +92,12 @@
{ 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_DELAY_B4_CHK_RDY }, /* CC.EN transition needs settle time */
+ { 0x2005106b, 0, 0, "Apple ANS2 NVMe Controller (T2)",
+ QUIRK_DELAY_B4_CHK_RDY | QUIRK_APPLE_SINGLE_VECTOR |
+ QUIRK_APPLE_128_BYTES_SQES | QUIRK_APPLE_SHARED_TAGS |
+ QUIRK_APPLE_NO_ASYNC_EVENT },
{ 0x00000000, 0, 0, NULL }
};
@@ -131,6 +136,14 @@
if (ep->devid)
ctrlr->quirks = ep->quirks;
+ /*
+ * Apple T2 ANS2 rejects IDENTIFY with CNS >= 2 (e.g., Active
+ * Namespace ID List), so cap to CNS 1. Internal identify commands
+ * (controller CNS=1, namespace CNS=0) are always within this limit.
+ */
+ if (ctrlr->quirks & QUIRK_APPLE_128_BYTES_SQES)
+ ctrlr->max_id_cns = 1;
+
if (ep->desc) {
device_set_desc(device, ep->desc);
return (BUS_PROBE_DEFAULT);
@@ -314,7 +327,7 @@
device_t dev;
int force_intx, num_io_queues, per_cpu_io_queues;
int min_cpus_per_ioq;
- int num_vectors_requested;
+ int num_vectors_requested, n;
dev = ctrlr->dev;
@@ -323,6 +336,19 @@
if (force_intx)
return (nvme_ctrlr_setup_shared(ctrlr, 0));
+ /*
+ * Apple T2 ANS2 only supports a single MSI vector and one IO queue.
+ * It has no MSI-X capability and no INTx pin.
+ */
+ if (ctrlr->quirks & QUIRK_APPLE_SINGLE_VECTOR) {
+ n = 1;
+ if (pci_alloc_msi(dev, &n) == 0) {
+ ctrlr->msi_count = n;
+ return (nvme_ctrlr_setup_shared(ctrlr, 1));
+ }
+ return (nvme_ctrlr_setup_shared(ctrlr, 0));
+ }
+
if (pci_msix_count(dev) == 0)
goto msi;
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,6 +165,8 @@
uint32_t num_entries;
uint32_t num_trackers;
+ uint32_t sqe_size; /* SQ entry size in bytes (64 or 128) */
+ uint16_t cid_base; /* CID offset for SHARED_TAGS IO queues */
uint32_t sq_tdbl_off;
uint32_t cq_hdbl_off;
@@ -220,10 +222,15 @@
int domain;
uint32_t ready_timeout_in_ms;
uint32_t quirks;
+ uint8_t max_id_cns; /* max CNS value for IDENTIFY (0 = no limit) */
#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 */
#define QUIRK_AHCI 8 /* Attached via AHCI redirect */
+#define QUIRK_APPLE_SINGLE_VECTOR 0x10 /* Single MSI vector (Apple T2) */
+#define QUIRK_APPLE_128_BYTES_SQES 0x20 /* 128-byte SQ entries (Apple T2) */
+#define QUIRK_APPLE_SHARED_TAGS 0x40 /* Admin/IO share CID space (Apple T2) */
+#define QUIRK_APPLE_NO_ASYNC_EVENT 0x80 /* No async event support (Apple T2) */
int resource_id;
struct resource *resource;
@@ -322,6 +329,14 @@
counter_u64_t alignment_splits;
};
+/*
+ * Access the idx'th submission queue entry, accounting for variable SQE size
+ * (64 bytes standard, 128 bytes for Apple T2 ANS2 IO queues).
+ */
+#define NVME_SQE(qpair, idx) \
+ ((struct nvme_command *)((uint8_t *)(qpair)->cmd + \
+ (idx) * (qpair)->sqe_size))
+
#define nvme_mmio_offsetof(reg) \
offsetof(struct nvme_registers, reg)
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
@@ -231,7 +231,7 @@
nvme_qpair_print_completion(qpair, cpl);
}
- qpair->act_tr[cpl->cid] = NULL;
+ qpair->act_tr[cpl->cid - qpair->cid_base] = NULL;
KASSERT(cpl->cid == req->cmd.cid, ("cpl cid does not match cmd cid\n"));
@@ -305,7 +305,7 @@
memset(&cpl, 0, sizeof(cpl));
cpl.sqid = qpair->id;
- cpl.cid = tr->cid;
+ cpl.cid = qpair->cid_base + tr->cid;
cpl.status = nvme_qpair_make_status(sct, sc, dnr);
nvme_qpair_complete_tracker(tr, &cpl, print_on_error);
}
@@ -433,8 +433,9 @@
NVME_STATUS_GET_P(status) == NVME_STATUS_GET_P(cpl.status),
("Phase unexpectedly inconsistent"));
- if (cpl.cid < qpair->num_trackers)
- tr = qpair->act_tr[cpl.cid];
+ if (cpl.cid >= qpair->cid_base &&
+ cpl.cid < qpair->cid_base + qpair->num_trackers)
+ tr = qpair->act_tr[cpl.cid - qpair->cid_base];
else
tr = NULL;
@@ -530,6 +531,26 @@
qpair->num_trackers = num_trackers;
qpair->ctrlr = ctrlr;
+ /*
+ * Apple T2 ANS2 quirks:
+ * - 128-byte SQ entries instead of standard 64-byte
+ * - SHARED_TAGS: IO queue CIDs must not overlap with admin CIDs (0..
+ * adminq.num_trackers-1), so IO queues start their CIDs at
+ * adminq.num_trackers.
+ */
+ /*
+ * Admin queue always uses 64-byte SQ entries per NVMe spec.
+ * APPLE_128_BYTES_SQES applies only to IO queues (CC.IOSQES).
+ */
+ if (qpair->id != 0 && (ctrlr->quirks & QUIRK_APPLE_128_BYTES_SQES))
+ qpair->sqe_size = 128;
+ else
+ qpair->sqe_size = sizeof(struct nvme_command);
+ if ((ctrlr->quirks & QUIRK_APPLE_SHARED_TAGS) && qpair->id != 0)
+ qpair->cid_base = ctrlr->adminq.num_trackers;
+ else
+ qpair->cid_base = 0;
+
mtx_init(&qpair->lock, "nvme qpair lock", NULL, MTX_DEF);
mtx_init(&qpair->recovery, "nvme qpair recovery", NULL, MTX_DEF);
@@ -553,7 +574,7 @@
* Each component must be page aligned, and individual PRP lists
* cannot cross a page boundary.
*/
- cmdsz = qpair->num_entries * sizeof(struct nvme_command);
+ cmdsz = qpair->num_entries * qpair->sqe_size;
cmdsz = roundup2(cmdsz, ctrlr->page_size);
cplsz = qpair->num_entries * sizeof(struct nvme_completion);
cplsz = roundup2(cplsz, ctrlr->page_size);
@@ -987,7 +1008,8 @@
* queue which will reset the card if it
* times out.
*/
- nvme_ctrlr_cmd_abort(ctrlr, tr->cid, qpair->id,
+ nvme_ctrlr_cmd_abort(ctrlr,
+ qpair->cid_base + tr->cid, qpair->id,
nvme_abort_complete, tr);
} else {
/*
@@ -1040,7 +1062,7 @@
mtx_assert(&qpair->lock, MA_OWNED);
req = tr->req;
- req->cmd.cid = tr->cid;
+ req->cmd.cid = qpair->cid_base + tr->cid;
qpair->act_tr[tr->cid] = tr;
ctrlr = qpair->ctrlr;
@@ -1061,7 +1083,7 @@
tr->deadline = SBT_MAX;
/* Copy the command from the tracker to the submission queue. */
- memcpy(&qpair->cmd[qpair->sq_tail], &req->cmd, sizeof(req->cmd));
+ memcpy(NVME_SQE(qpair, qpair->sq_tail), &req->cmd, sizeof(req->cmd));
if (++qpair->sq_tail == qpair->num_entries)
qpair->sq_tail = 0;
@@ -1235,7 +1257,7 @@
qpair->phase = 1;
memset(qpair->cmd, 0,
- qpair->num_entries * sizeof(struct nvme_command));
+ qpair->num_entries * qpair->sqe_size);
memset(qpair->cpl, 0,
qpair->num_entries * sizeof(struct nvme_completion));
}
diff --git a/sys/dev/nvme/nvme_sim.c b/sys/dev/nvme/nvme_sim.c
--- a/sys/dev/nvme/nvme_sim.c
+++ b/sys/dev/nvme/nvme_sim.c
@@ -96,6 +96,20 @@
struct nvme_controller *ctrlr;
ctrlr = sim2ctrlr(sim);
+
+ /*
+ * Some controllers (e.g., Apple T2 ANS2) do not support IDENTIFY
+ * with CNS values above a device-specific limit. Reject early to
+ * avoid confusing the firmware.
+ */
+ if (ctrlr->max_id_cns != 0 &&
+ nvmeio->cmd.opc == NVME_OPC_IDENTIFY &&
+ (le32toh(nvmeio->cmd.cdw10) & 0xff) > ctrlr->max_id_cns) {
+ nvmeio->ccb_h.status = CAM_REQ_INVALID;
+ xpt_done(ccb);
+ return;
+ }
+
payload = nvmeio->data_ptr;
size = nvmeio->dxfer_len;
/* SG LIST ??? */
diff --git a/sys/dev/nvme/nvme_sysctl.c b/sys/dev/nvme/nvme_sysctl.c
--- a/sys/dev/nvme/nvme_sysctl.c
+++ b/sys/dev/nvme/nvme_sysctl.c
@@ -69,7 +69,7 @@
printf("Submission queue:\n");
for (i = 0; i < qpair->num_entries; i++) {
- cmd = &qpair->cmd[i];
+ cmd = NVME_SQE(qpair, i);
printf("%05d: ", i);
nvme_qpair_print_command(qpair, cmd);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, May 23, 4:52 PM (18 h, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33450057
Default Alt Text
D57087.id178274.diff (10 KB)
Attached To
Mode
D57087: nvme: add Apple T2 ANS2 NVMe quirks
Attached
Detach File
Event Timeline
Log In to Comment