Apple controllers seem to require any queue buffers on the admin queue
to be aligned to the NVMe controller page size. Weirdly, this constraint
does not apply to the i/o queue where any alignment is fine. This has
always been required on pre-M1 controllers and is required starting with
macOS 15 firmware or post-M4 controllers again. On M1/M2/M3 there was a
chicken bit to disable this requirement.

U-boot appears to always use page-aligned buffers for the admin queue.
Add WARN_ON_ONCE to make it very obvious if/when that changes or wasn't
true to begin with.

Signed-off-by: Janne Grunau <[email protected]>
---
 drivers/nvme/nvme_apple.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/nvme/nvme_apple.c b/drivers/nvme/nvme_apple.c
index f615f8fac4a..54821f80c81 100644
--- a/drivers/nvme/nvme_apple.c
+++ b/drivers/nvme/nvme_apple.c
@@ -12,6 +12,7 @@
 #include <asm/io.h>
 #include <asm/arch/rtkit.h>
 #include <asm/arch/sart.h>
+#include <linux/bug.h>
 #include <linux/iopoll.h>
 #include <linux/sizes.h>
 
@@ -116,9 +117,15 @@ static void apple_nvme_submit_cmd(struct nvme_queue *nvmeq,
 {
        struct apple_nvme_priv *priv =
                container_of(nvmeq->dev, struct apple_nvme_priv, ndev);
+       u32 page_size = nvmeq->dev->page_size;
        struct ans_nvmmu_tcb *tcb;
        u16 tail = nvmeq->sq_tail;
 
+       if (nvmeq->qid == NVME_ADMIN_Q) {
+               WARN_ON_ONCE(!IS_ALIGNED(cmd->common.prp1, page_size));
+               WARN_ON_ONCE(!IS_ALIGNED(cmd->common.prp2, page_size));
+       }
+
        tcb = ((void *)priv->tcbs[nvmeq->qid]) + tail * ANS_NVMMU_TCB_PITCH;
        memset(tcb, 0, sizeof(*tcb));
        tcb->opcode = 0;

-- 
2.55.0

Reply via email to