diff --git a/0004-nvme-Record-maximum-allowed-request-size.patch b/0004-nvme-Record-maximum-allowed-request-size.patch new file mode 100644 index 0000000..303a957 --- /dev/null +++ b/0004-nvme-Record-maximum-allowed-request-size.patch @@ -0,0 +1,80 @@ +From c021d44d0d4915a2b152d29abde5f1d4cb7b8ddd Mon Sep 17 00:00:00 2001 +From: Alexander Graf +Date: Wed, 30 Sep 2020 23:10:53 +0200 +Subject: [PATCH] nvme: Record maximum allowed request size + +NVMe has a limit on how many sectors it can handle at most within a single +request. Remember that number, so that in a follow-up patch, we can verify +that we don't exceed it. + +Signed-off-by: Alexander Graf +(cherry picked from commit b68f313c9139e480a9f5a0d1b5aa6f294b86d982) +--- + src/hw/nvme-int.h | 8 +++++++- + src/hw/nvme.c | 13 +++++++++++-- + 2 files changed, 18 insertions(+), 3 deletions(-) + +diff --git a/src/hw/nvme-int.h b/src/hw/nvme-int.h +index 9f95dd8..674008a 100644 +--- a/src/hw/nvme-int.h ++++ b/src/hw/nvme-int.h +@@ -117,6 +117,7 @@ struct nvme_namespace { + + u32 block_size; + u32 metadata_size; ++ u32 max_req_size; + + /* Page aligned buffer of size NVME_PAGE_SIZE. */ + char *dma_buffer; +@@ -131,7 +132,12 @@ struct nvme_identify_ctrl { + char mn[40]; + char fr[8]; + +- char _boring[516 - 72]; ++ u8 rab; ++ u8 ieee[3]; ++ u8 cmic; ++ u8 mdts; ++ ++ char _boring[516 - 78]; + + u32 nn; /* number of namespaces */ + }; +diff --git a/src/hw/nvme.c b/src/hw/nvme.c +index 6a01204..5bc2586 100644 +--- a/src/hw/nvme.c ++++ b/src/hw/nvme.c +@@ -238,7 +238,8 @@ nvme_admin_identify_ns(struct nvme_ctrl *ctrl, u32 ns_id) + } + + static void +-nvme_probe_ns(struct nvme_ctrl *ctrl, struct nvme_namespace *ns, u32 ns_id) ++nvme_probe_ns(struct nvme_ctrl *ctrl, struct nvme_namespace *ns, u32 ns_id, ++ u8 mdts) + { + ns->ctrl = ctrl; + ns->ns_id = ns_id; +@@ -281,6 +282,14 @@ nvme_probe_ns(struct nvme_ctrl *ctrl, struct nvme_namespace *ns, u32 ns_id) + ns->drive.blksize = ns->block_size; + ns->drive.sectors = ns->lba_count; + ++ if (mdts) { ++ ns->max_req_size = ((1U << mdts) * NVME_PAGE_SIZE) / ns->block_size; ++ dprintf(3, "NVME NS %u max request size: %d sectors\n", ++ ns_id, ns->max_req_size); ++ } else { ++ ns->max_req_size = -1U; ++ } ++ + ns->dma_buffer = zalloc_page_aligned(&ZoneHigh, NVME_PAGE_SIZE); + + char *desc = znprintf(MAXDESCSIZE, "NVMe NS %u: %llu MiB (%llu %u-byte " +@@ -567,7 +576,7 @@ nvme_controller_enable(struct nvme_ctrl *ctrl) + /* Populate namespace IDs */ + int ns_idx; + for (ns_idx = 0; ns_idx < ctrl->ns_count; ns_idx++) { +- nvme_probe_ns(ctrl, &ctrl->ns[ns_idx], ns_idx + 1); ++ nvme_probe_ns(ctrl, &ctrl->ns[ns_idx], ns_idx + 1, identify->mdts); + } + + dprintf(3, "NVMe initialization complete!\n"); diff --git a/0005-nvme-improve-namespace-allocation.patch b/0005-nvme-improve-namespace-allocation.patch new file mode 100644 index 0000000..818a975 --- /dev/null +++ b/0005-nvme-improve-namespace-allocation.patch @@ -0,0 +1,123 @@ +From f2522cde64a70ea215826052b4cabeda84f0cace Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 26 May 2021 09:32:10 +0200 +Subject: [PATCH] nvme: improve namespace allocation + +Instead of allocating a big array upfront go probe the namespaces and +only allocate an nvme_namespace struct for those namespaces which are +actually active. + +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 9bb1203b359dff5b36e8e6d0afcfc6fc2c1f8e78) +--- + src/hw/nvme-int.h | 1 - + src/hw/nvme.c | 40 ++++++++++++++++------------------------ + 2 files changed, 16 insertions(+), 25 deletions(-) + +diff --git a/src/hw/nvme-int.h b/src/hw/nvme-int.h +index 674008a..7cade8c 100644 +--- a/src/hw/nvme-int.h ++++ b/src/hw/nvme-int.h +@@ -101,7 +101,6 @@ struct nvme_ctrl { + struct nvme_cq admin_cq; + + u32 ns_count; +- struct nvme_namespace *ns; + + struct nvme_sq io_sq; + struct nvme_cq io_cq; +diff --git a/src/hw/nvme.c b/src/hw/nvme.c +index 5bc2586..7910b15 100644 +--- a/src/hw/nvme.c ++++ b/src/hw/nvme.c +@@ -238,11 +238,9 @@ nvme_admin_identify_ns(struct nvme_ctrl *ctrl, u32 ns_id) + } + + static void +-nvme_probe_ns(struct nvme_ctrl *ctrl, struct nvme_namespace *ns, u32 ns_id, +- u8 mdts) ++nvme_probe_ns(struct nvme_ctrl *ctrl, u32 ns_idx, u8 mdts) + { +- ns->ctrl = ctrl; +- ns->ns_id = ns_id; ++ u32 ns_id = ns_idx + 1; + + struct nvme_identify_ns *id = nvme_admin_identify_ns(ctrl, ns_id); + if (!id) { +@@ -258,12 +256,21 @@ nvme_probe_ns(struct nvme_ctrl *ctrl, struct nvme_namespace *ns, u32 ns_id, + goto free_buffer; + } + +- ns->lba_count = id->nsze; +- if (!ns->lba_count) { ++ if (!id->nsze) { + dprintf(2, "NVMe NS %u is inactive.\n", ns_id); + goto free_buffer; + } + ++ struct nvme_namespace *ns = malloc_fseg(sizeof(*ns)); ++ if (!ns) { ++ warn_noalloc(); ++ goto free_buffer; ++ } ++ memset(ns, 0, sizeof(*ns)); ++ ns->ctrl = ctrl; ++ ns->ns_id = ns_id; ++ ns->lba_count = id->nsze; ++ + struct nvme_lba_format *fmt = &id->lbaf[current_lba_format]; + + ns->block_size = 1U << fmt->lbads; +@@ -273,10 +280,11 @@ nvme_probe_ns(struct nvme_ctrl *ctrl, struct nvme_namespace *ns, u32 ns_id, + /* If we see devices that trigger this path, we need to increase our + buffer size. */ + warn_internalerror(); ++ free(ns); + goto free_buffer; + } + +- ns->drive.cntl_id = ns - ctrl->ns; ++ ns->drive.cntl_id = ns_idx; + ns->drive.removable = 0; + ns->drive.type = DTYPE_NVME; + ns->drive.blksize = ns->block_size; +@@ -466,13 +474,6 @@ nvme_create_io_queues(struct nvme_ctrl *ctrl) + return -1; + } + +-static void +-nvme_destroy_io_queues(struct nvme_ctrl *ctrl) +-{ +- nvme_destroy_sq(&ctrl->io_sq); +- nvme_destroy_cq(&ctrl->io_cq); +-} +- + /* Waits for CSTS.RDY to match rdy. Returns 0 on success. */ + static int + nvme_wait_csts_rdy(struct nvme_ctrl *ctrl, unsigned rdy) +@@ -566,24 +567,15 @@ nvme_controller_enable(struct nvme_ctrl *ctrl) + goto err_destroy_admin_sq; + } + +- ctrl->ns = malloc_fseg(sizeof(*ctrl->ns) * ctrl->ns_count); +- if (!ctrl->ns) { +- warn_noalloc(); +- goto err_destroy_ioq; +- } +- memset(ctrl->ns, 0, sizeof(*ctrl->ns) * ctrl->ns_count); +- + /* Populate namespace IDs */ + int ns_idx; + for (ns_idx = 0; ns_idx < ctrl->ns_count; ns_idx++) { +- nvme_probe_ns(ctrl, &ctrl->ns[ns_idx], ns_idx + 1, identify->mdts); ++ nvme_probe_ns(ctrl, ns_idx, identify->mdts); + } + + dprintf(3, "NVMe initialization complete!\n"); + return 0; + +- err_destroy_ioq: +- nvme_destroy_io_queues(ctrl); + err_destroy_admin_sq: + nvme_destroy_sq(&ctrl->admin_sq); + err_destroy_admin_cq: diff --git a/seabios.spec b/seabios.spec index f48a5b0..85a985f 100644 --- a/seabios.spec +++ b/seabios.spec @@ -4,7 +4,7 @@ Name: seabios Version: 1.14.0 -Release: 2%{?dist} +Release: 3%{?dist} Summary: Open-source legacy BIOS implementation License: LGPLv3 @@ -15,6 +15,8 @@ Source0: http://code.coreboot.org/p/seabios/downloads/get/%{name}-%{versi Patch0001: 0001-Workaround-for-a-win8.1-32-S4-resume-bug.patch Patch0002: 0002-reserve-more-memory-on-fseg.patch Patch0003: 0003-vgabios-Reorder-video-modes-to-work-around-a-Windows.patch +Patch0004: 0004-nvme-Record-maximum-allowed-request-size.patch +Patch0005: 0005-nvme-improve-namespace-allocation.patch Source10: config.vga-cirrus Source11: config.vga-isavga @@ -160,6 +162,9 @@ install -m 0644 binaries/vgabios*.bin $RPM_BUILD_ROOT%{_datadir}/seavgabios %changelog +* Wed Jun 02 2021 Cole Robinson - 1.14.0-3 +- Fix boot from nvme (bz 1963255) + * Wed Jan 27 2021 Fedora Release Engineering - 1.14.0-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild