forked from openwrt/openwrt
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
uboot-mvebu: backport patch to fix nvme detail crash
Steps to reproduce: 1. Insert NVMe disk with a reduction to Turris Omnia 2. Go to U-boot 3. Run these two commands: a) ``nvme scan`` b) ``nvme detail`` 4. Wait for crash This is backported from U-boot upstream repository. It should be included in the upcoming release - 2022.04 [1]. It was tested on Turris Omnia, mvebu, cortex-a9, OpenWrt master. [1] https://patchwork.ozlabs.org/project/uboot/patch/20211209100639.21530-1-pali@kernel.org/ Signed-off-by: Josef Schlehofer <pepe.schlehofer@gmail.com> [Export the patch from U-Boot git] Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
- Loading branch information
Showing
1 changed file
with
92 additions
and
0 deletions.
There are no files selected for viewing
92 changes: 92 additions & 0 deletions
92
package/boot/uboot-mvebu/patches/012-nvme-Do-not-allocate-8kB-buffer-on-stack.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
From d17ab6e1289b1d705c75de8a2351218962fb7352 Mon Sep 17 00:00:00 2001 | ||
From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org> | ||
Date: Thu, 9 Dec 2021 11:06:39 +0100 | ||
Subject: [PATCH] nvme: Do not allocate 8kB buffer on stack | ||
MIME-Version: 1.0 | ||
Content-Type: text/plain; charset=UTF-8 | ||
Content-Transfer-Encoding: 8bit | ||
|
||
Calling 'nvme scan' followed by 'nvme detail' crashes U-Boot on Turris | ||
Omnia with the following error: | ||
|
||
undefined instruction | ||
pc : [<0a000000>] lr : [<7ff80bfc>] | ||
reloc pc : [<8a8c0000>] lr : [<00840bfc>] | ||
sp : 7fb2b908 ip : 0000002a fp : 02000000 | ||
r10: 04000000 r9 : 7fb2fed0 r8 : e1000000 | ||
r7 : 0c000000 r6 : 03000000 r5 : 06000000 r4 : 01000000 | ||
r3 : 7fb30928 r2 : 7fb30928 r1 : 00000000 r0 : 00000000 | ||
Flags: nZCv IRQs off FIQs off Mode SVC_32 | ||
Code: 0f0fb4f0 0f0fb4f0 0f0fb4f0 0f0fb4f0 (f0f04b0f) | ||
Resetting CPU ... | ||
|
||
This happens when nvme_print_info() tries to return to the caller. It | ||
looks like this error is caused by trying to allocate 8 KiB of memory | ||
on the stack by the two uses of ALLOC_CACHE_ALIGN_BUFFER(). | ||
|
||
Use malloc_cache_aligned() to allocate this memory dynamically instead. | ||
|
||
This fixes 'nvme detail' on Turris Omnia. | ||
|
||
Note that similar change was applied to file drivers/nvme/nvme.c in past by | ||
commit 2f83481dff9c ("nvme: use page-aligned buffer for identify command"). | ||
|
||
Signed-off-by: Pali Rohár <pali@kernel.org> | ||
Signed-off-by: Marek Behún <marek.behun@nic.cz> | ||
--- | ||
drivers/nvme/nvme_show.c | 35 ++++++++++++++++++++++++++--------- | ||
1 file changed, 26 insertions(+), 9 deletions(-) | ||
|
||
--- a/drivers/nvme/nvme_show.c | ||
+++ b/drivers/nvme/nvme_show.c | ||
@@ -106,24 +106,41 @@ int nvme_print_info(struct udevice *udev | ||
{ | ||
struct nvme_ns *ns = dev_get_priv(udev); | ||
struct nvme_dev *dev = ns->dev; | ||
- ALLOC_CACHE_ALIGN_BUFFER(char, buf_ns, sizeof(struct nvme_id_ns)); | ||
- struct nvme_id_ns *id = (struct nvme_id_ns *)buf_ns; | ||
- ALLOC_CACHE_ALIGN_BUFFER(char, buf_ctrl, sizeof(struct nvme_id_ctrl)); | ||
- struct nvme_id_ctrl *ctrl = (struct nvme_id_ctrl *)buf_ctrl; | ||
+ struct nvme_id_ctrl *ctrl; | ||
+ struct nvme_id_ns *id; | ||
+ int ret = 0; | ||
|
||
- if (nvme_identify(dev, 0, 1, (dma_addr_t)(long)ctrl)) | ||
- return -EIO; | ||
+ ctrl = memalign(dev->page_size, sizeof(struct nvme_id_ctrl)); | ||
+ if (!ctrl) | ||
+ return -ENOMEM; | ||
+ | ||
+ if (nvme_identify(dev, 0, 1, (dma_addr_t)(long)ctrl)) { | ||
+ ret = -EIO; | ||
+ goto free_ctrl; | ||
+ } | ||
|
||
print_optional_admin_cmd(le16_to_cpu(ctrl->oacs), ns->devnum); | ||
print_optional_nvm_cmd(le16_to_cpu(ctrl->oncs), ns->devnum); | ||
print_format_nvme_attributes(ctrl->fna, ns->devnum); | ||
|
||
- if (nvme_identify(dev, ns->ns_id, 0, (dma_addr_t)(long)id)) | ||
- return -EIO; | ||
+ id = memalign(dev->page_size, sizeof(struct nvme_id_ns)); | ||
+ if (!id) { | ||
+ ret = -ENOMEM; | ||
+ goto free_ctrl; | ||
+ } | ||
+ | ||
+ if (nvme_identify(dev, ns->ns_id, 0, (dma_addr_t)(long)id)) { | ||
+ ret = -EIO; | ||
+ goto free_id; | ||
+ } | ||
|
||
print_formats(id, ns); | ||
print_data_protect_cap(id->dpc, ns->devnum); | ||
print_metadata_cap(id->mc, ns->devnum); | ||
|
||
- return 0; | ||
+free_id: | ||
+ free(id); | ||
+free_ctrl: | ||
+ free(ctrl); | ||
+ return ret; | ||
} |