[PATCH 4/6] nvme: Add a quirk for page aligned admin queue buffers
Sven Peter <[email protected]> Thu, 06 Aug 2026 17:27:36 +0200
| Newsgroups | org.infradead.lists.linux-nvme,dev.linux.lists.asahi,org.infradead.lists.linux-arm-kernel,org.kernel.feeds.b4-sent,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
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 we only got away with this because there was a chicken bit to disable this requirement. Let's add a quirk that enforces this alignment. Signed-off-by: Sven Peter <[email protected]> --- drivers/nvme/host/core.c | 5 ++++- drivers/nvme/host/nvme.h | 7 +++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 453c1f0b2dd0..b76f4e4d8850 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -2071,7 +2071,10 @@ static void nvme_set_ctrl_limits(struct nvme_ctrl *ctrl, lim->max_integrity_segments = ctrl->max_integrity_segments; lim->virt_boundary_mask = ctrl->ops->get_virt_boundary(ctrl, is_admin); lim->max_segment_size = UINT_MAX; - lim->dma_alignment = 3; + if (is_admin && (ctrl->quirks & NVME_QUIRK_ADMIN_PAGE_ALIGN)) + lim->dma_alignment = NVME_CTRL_PAGE_SIZE - 1; + else + lim->dma_alignment = 3; } static bool nvme_update_disk_info(struct nvme_ns *ns, struct nvme_id_ns *id, diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 824651cc898d..957ded0c6f53 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -178,6 +178,11 @@ enum nvme_quirks { * Align dma pool segment size to 512 bytes */ NVME_QUIRK_DMAPOOL_ALIGN_512 = (1 << 22), + + /* + * Admin queue DMA buffers must be page aligned + */ + NVME_QUIRK_ADMIN_PAGE_ALIGN = (1 << 23), }; static inline char *nvme_quirk_name(enum nvme_quirks q) @@ -229,6 +234,8 @@ static inline char *nvme_quirk_name(enum nvme_quirks q) return "broken_msi"; case NVME_QUIRK_DMAPOOL_ALIGN_512: return "dmapool_align_512"; + case NVME_QUIRK_ADMIN_PAGE_ALIGN: + return "admin_page_align"; } return "unknown"; -- 2.55.0