Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
lx2160a_build
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Boxiang Sun
lx2160a_build
Commits
abaeb8cd
Commit
abaeb8cd
authored
Nov 26, 2019
by
Rabeeh Khoury
Committed by
GitHub
Nov 26, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #10 from olofj/nvme-fixes
patches: u-boot: add nvme fixes from upstream
parents
2d6fd683
30193329
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
387 additions
and
0 deletions
+387
-0
patches/u-boot/0010-nvme-Fix-warning-of-cast-from-pointer-to-integer-of-.patch
...vme-Fix-warning-of-cast-from-pointer-to-integer-of-.patch
+63
-0
patches/u-boot/0011-nvme-Fix-PRP-Offset-Invalid.patch
patches/u-boot/0011-nvme-Fix-PRP-Offset-Invalid.patch
+95
-0
patches/u-boot/0012-nvme-add-accessor-to-namespace-id-and-eui64.patch
...ot/0012-nvme-add-accessor-to-namespace-id-and-eui64.patch
+88
-0
patches/u-boot/0013-nvme-flush-dcache-on-both-r-w-and-the-prp-list.patch
...0013-nvme-flush-dcache-on-both-r-w-and-the-prp-list.patch
+49
-0
patches/u-boot/0014-nvme-use-page-aligned-buffer-for-identify-command.patch
...4-nvme-use-page-aligned-buffer-for-identify-command.patch
+92
-0
No files found.
patches/u-boot/0010-nvme-Fix-warning-of-cast-from-pointer-to-integer-of-.patch
0 → 100644
View file @
abaeb8cd
From bd424e17884a25848ef858695133f773873c818c Mon Sep 17 00:00:00 2001
From: Bin Meng <bmeng.cn@gmail.com>
Date: Wed, 15 May 2019 08:37:56 -0700
Subject: [PATCH 1/5] nvme: Fix warning of cast from pointer to integer of
different size
When dma_addr_t is u32 in 64-bit, there are some warnings when
building NVME driver. Fix it by doing an additional (long) cast.
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
(cherry
picked from commit 5b2a20e9564c46a571126275991426dd8618e2d8)
Signed-off-by: Olof Johansson <olof@lixom.net>
---
drivers/nvme/nvme.c | 4 ++--
drivers/nvme/nvme_show.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
index 1ee0a0aefb..d4965e2ef6 100644
--- a/drivers/nvme/nvme.c
+++ b/drivers/nvme/nvme.c
@@ -577,7 +577,7 @@
static int nvme_get_info_from_identify(struct nvme_dev *dev)
int ret;
int shift = NVME_CAP_MPSMIN(dev->cap) + 12;
- ret = nvme_identify(dev, 0, 1, (dma_addr_t)ctrl);
+ ret = nvme_identify(dev, 0, 1, (dma_addr_t)(long)ctrl);
if (ret)
return -EIO;
@@ -646,7 +646,7 @@
static int nvme_blk_probe(struct udevice *udev)
ns->dev = ndev;
/* extract the namespace id from the block device name */
ns->ns_id = trailing_strtol(udev->name) + 1;
- if (nvme_identify(ndev, ns->ns_id, 0, (dma_addr_t)id))
+ if (nvme_identify(ndev, ns->ns_id, 0, (dma_addr_t)(long)id))
return -EIO;
flbas = id->flbas & NVME_NS_FLBAS_LBA_MASK;
diff --git a/drivers/nvme/nvme_show.c b/drivers/nvme/nvme_show.c
index 395b0618e6..15e459da1a 100644
--- a/drivers/nvme/nvme_show.c
+++ b/drivers/nvme/nvme_show.c
@@ -111,14 +111,14 @@
int nvme_print_info(struct udevice *udev)
ALLOC_CACHE_ALIGN_BUFFER(char, buf_ctrl, sizeof(struct nvme_id_ctrl));
struct nvme_id_ctrl *ctrl = (struct nvme_id_ctrl *)buf_ctrl;
- if (nvme_identify(dev, 0, 1, (dma_addr_t)ctrl))
+ if (nvme_identify(dev, 0, 1, (dma_addr_t)(long)ctrl))
return -EIO;
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)id))
+ if (nvme_identify(dev, ns->ns_id, 0, (dma_addr_t)(long)id))
return -EIO;
print_formats(id, ns);
--
2.22.GIT
patches/u-boot/0011-nvme-Fix-PRP-Offset-Invalid.patch
0 → 100644
View file @
abaeb8cd
From 8c131511be5c0966c32989b1bf802951a783e1b0 Mon Sep 17 00:00:00 2001
From: Aaron Williams <awilliams@marvell.com>
Date: Thu, 22 Aug 2019 20:37:26 -0700
Subject: [PATCH 2/5] nvme: Fix PRP Offset Invalid
When large writes take place I saw a Samsung EVO 970+ return a status
value of 0x13, PRP Offset Invalid. I tracked this down to the
improper handling of PRP entries. The blocks the PRP entries are
placed in cannot cross a page boundary and thus should be allocated
on page boundaries. This is how the Linux kernel driver works.
With this patch, the PRP pool is allocated on a page boundary and
other than the very first allocation, the pool size is a multiple of
the page size. Each page can hold (4096 / 8) - 1 entries since the
last entry must point to the next page in the pool.
Signed-off-by: Aaron Williams <awilliams@marvell.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
(cherry
picked from commit b21dcebfa6b372cd91bf42a30f1d8a1a525f329b)
Signed-off-by: Olof Johansson <olof@lixom.net>
---
drivers/nvme/nvme.c | 29 +++++++++++++++++++----------
1 file changed, 19 insertions(+), 10 deletions(-)
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
index d4965e2ef6..47f101e280 100644
--- a/drivers/nvme/nvme.c
+++ b/drivers/nvme/nvme.c
@@ -73,6 +73,9 @@
static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
u64 *prp_pool;
int length = total_len;
int i, nprps;
+ u32 prps_per_page = (page_size >> 3) - 1;
+ u32 num_pages;
+
length -= (page_size - offset);
if (length <= 0) {
@@ -89,15 +92,20 @@
static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
}
nprps = DIV_ROUND_UP(length, page_size);
+ num_pages = DIV_ROUND_UP(nprps, prps_per_page);
if (nprps > dev->prp_entry_num) {
free(dev->prp_pool);
- dev->prp_pool = malloc(nprps << 3);
+ /*
+ * Always increase in increments of pages. It doesn't waste
+ * much memory and reduces the number of allocations.
+ */
+ dev->prp_pool = memalign(page_size, num_pages * page_size);
if (!dev->prp_pool) {
printf("Error: malloc prp_pool fail\n");
return -ENOMEM;
}
- dev->prp_entry_num = nprps;
+ dev->prp_entry_num = prps_per_page * num_pages;
}
prp_pool = dev->prp_pool;
@@ -788,14 +796,6 @@
static int nvme_probe(struct udevice *udev)
}
memset(ndev->queues, 0, NVME_Q_NUM * sizeof(struct nvme_queue *));
- ndev->prp_pool = malloc(MAX_PRP_POOL);
- if (!ndev->prp_pool) {
- ret = -ENOMEM;
- printf("Error: %s: Out of memory!\n", udev->name);
- goto free_nvme;
- }
- ndev->prp_entry_num = MAX_PRP_POOL >> 3;
-
ndev->cap = nvme_readq(&ndev->bar->cap);
ndev->q_depth = min_t(int, NVME_CAP_MQES(ndev->cap) + 1, NVME_Q_DEPTH);
ndev->db_stride = 1 << NVME_CAP_STRIDE(ndev->cap);
@@ -805,6 +805,15 @@
static int nvme_probe(struct udevice *udev)
if (ret)
goto free_queue;
+ /* Allocate after the page size is known */
+ ndev->prp_pool = memalign(ndev->page_size, MAX_PRP_POOL);
+ if (!ndev->prp_pool) {
+ ret = -ENOMEM;
+ printf("Error: %s: Out of memory!\n", udev->name);
+ goto free_nvme;
+ }
+ ndev->prp_entry_num = MAX_PRP_POOL >> 3;
+
ret = nvme_setup_io_queues(ndev);
if (ret)
goto free_queue;
--
2.22.GIT
patches/u-boot/0012-nvme-add-accessor-to-namespace-id-and-eui64.patch
0 → 100644
View file @
abaeb8cd
From 89eaac0cd956214260038ed39be675f9a3af220a Mon Sep 17 00:00:00 2001
From: Patrick Wildt <patrick@blueri.se>
Date: Thu, 3 Oct 2019 13:48:47 +0200
Subject: [PATCH 3/5] nvme: add accessor to namespace id and eui64
This adds a function which can be used by e.g. EFI to retrieve
the namespace identifier and EUI64. For that it adds the EUI64
to its driver internal namespace structure and copies the EUI64
during namespace identification.
Signed-off-by: Patrick Wildt <patrick@blueri.se>
Tested-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
(cherry
picked from commit c50b2883dfc1ce355dc37238741ef97cd2c5d000)
Signed-off-by: Olof Johansson <olof@lixom.net>
---
drivers/nvme/nvme.c | 13 +++++++++++++
drivers/nvme/nvme.h | 1 +
include/nvme.h | 12 ++++++++++++
3 files changed, 26 insertions(+)
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
index 47f101e280..ee6b581d9e 100644
--- a/drivers/nvme/nvme.c
+++ b/drivers/nvme/nvme.c
@@ -621,6 +621,18 @@
static int nvme_get_info_from_identify(struct nvme_dev *dev)
return 0;
}
+int nvme_get_namespace_id(struct udevice *udev, u32 *ns_id, u8 *eui64)
+{
+ struct nvme_ns *ns = dev_get_priv(udev);
+
+ if (ns_id)
+ *ns_id = ns->ns_id;
+ if (eui64)
+ memcpy(eui64, ns->eui64, sizeof(ns->eui64));
+
+ return 0;
+}
+
int nvme_scan_namespace(void)
{
struct uclass *uc;
@@ -657,6 +669,7 @@
static int nvme_blk_probe(struct udevice *udev)
if (nvme_identify(ndev, ns->ns_id, 0, (dma_addr_t)(long)id))
return -EIO;
+ memcpy(&ns->eui64, &id->eui64, sizeof(id->eui64));
flbas = id->flbas & NVME_NS_FLBAS_LBA_MASK;
ns->flbas = flbas;
ns->lba_shift = id->lbaf[flbas].ds;
diff --git a/drivers/nvme/nvme.h b/drivers/nvme/nvme.h
index 922f7abfe8..0e8cb221a7 100644
--- a/drivers/nvme/nvme.h
+++ b/drivers/nvme/nvme.h
@@ -637,6 +637,7 @@
struct nvme_ns {
struct list_head list;
struct nvme_dev *dev;
unsigned ns_id;
+ u8 eui64[8];
int devnum;
int lba_shift;
u8 flbas;
diff --git a/include/nvme.h b/include/nvme.h
index 2c3d14d241..2cdf8ce320 100644
--- a/include/nvme.h
+++ b/include/nvme.h
@@ -78,4 +78,16 @@
int nvme_scan_namespace(void);
*/
int nvme_print_info(struct udevice *udev);
+/**
+ * nvme_get_namespace_id - return namespace identifier
+ *
+ * This returns the namespace identifier.
+ *
+ * @udev: NVMe controller device
+ * @ns_id: Place where to put the name space identifier
+ * @eui64: Place where to put the IEEE Extended Unique Identifier
+ * @return: 0 on success, -ve on error
+ */
+int nvme_get_namespace_id(struct udevice *udev, u32 *ns_id, u8 *eui64);
+
#endif /* __NVME_H__ */
--
2.22.GIT
patches/u-boot/0013-nvme-flush-dcache-on-both-r-w-and-the-prp-list.patch
0 → 100644
View file @
abaeb8cd
From 7846531d2ad011cb2d025aac92aeefb3dffec429 Mon Sep 17 00:00:00 2001
From: Patrick Wildt <patrick@blueri.se>
Date: Wed, 16 Oct 2019 23:22:50 +0200
Subject: [PATCH 4/5] nvme: flush dcache on both r/w, and the prp list
It's possible that the data cache for the buffer still holds data
to be flushed to memory, since the buffer was probably used as stack
before. Thus we need to make sure to flush it also on reads, since
it's possible that the cache is automatically flused to memory after
the NVMe DMA transfer happened, thus overwriting the NVMe transfer's
data. Also add a missing dcache flush for the prp list.
Signed-off-by: Patrick Wildt <patrick@blueri.se>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
(cherry
picked from commit 8c403402ca691c967516481b6bc2c879d683a73d)
Signed-off-by: Olof Johansson <olof@lixom.net>
---
drivers/nvme/nvme.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
index ee6b581d9e..53ff6e89aa 100644
--- a/drivers/nvme/nvme.c
+++ b/drivers/nvme/nvme.c
@@ -123,6 +123,9 @@
static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
}
*prp2 = (ulong)dev->prp_pool;
+ flush_dcache_range((ulong)dev->prp_pool, (ulong)dev->prp_pool +
+ dev->prp_entry_num * sizeof(u64));
+
return 0;
}
@@ -705,9 +708,8 @@
static ulong nvme_blk_rw(struct udevice *udev, lbaint_t blknr,
u16 lbas = 1 << (dev->max_transfer_shift - ns->lba_shift);
u64 total_lbas = blkcnt;
- if (!read)
- flush_dcache_range((unsigned long)buffer,
- (unsigned long)buffer + total_len);
+ flush_dcache_range((unsigned long)buffer,
+ (unsigned long)buffer + total_len);
c.rw.opcode = read ? nvme_cmd_read : nvme_cmd_write;
c.rw.flags = 0;
--
2.22.GIT
patches/u-boot/0014-nvme-use-page-aligned-buffer-for-identify-command.patch
0 → 100644
View file @
abaeb8cd
From 489ce106e10a3df390ea19267729e4102e88a63a Mon Sep 17 00:00:00 2001
From: Patrick Wildt <patrick@blueri.se>
Date: Wed, 16 Oct 2019 08:42:04 +0200
Subject: [PATCH 5/5] nvme: use page-aligned buffer for identify command
Change the stack-allocated buffer for the identification command
to explicitly allocate page-aligned buffers. Even though the spec
seems to allow having admin queue commands on non page-aligned
buffers, it seems to not be possible on my i.MX8MQ board with a
a Silicon Power P34A80. Since all of the NVMe drivers I have seen
always do admin commands on a page-aligned buffer, which does work
on my system, it makes sense for us to do that as well.
Signed-off-by: Patrick Wildt <patrick@blueri.se>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
(cherry
picked from commit 2f83481dff9c4f253a6ac341911d78d4984ca07b)
Signed-off-by: Olof Johansson <olof@lixom.net>
---
drivers/nvme/nvme.c | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
index 53ff6e89aa..f915817aaa 100644
--- a/drivers/nvme/nvme.c
+++ b/drivers/nvme/nvme.c
@@ -583,14 +583,19 @@
static int nvme_setup_io_queues(struct nvme_dev *dev)
static int nvme_get_info_from_identify(struct nvme_dev *dev)
{
- ALLOC_CACHE_ALIGN_BUFFER(char, buf, sizeof(struct nvme_id_ctrl));
- struct nvme_id_ctrl *ctrl = (struct nvme_id_ctrl *)buf;
+ struct nvme_id_ctrl *ctrl;
int ret;
int shift = NVME_CAP_MPSMIN(dev->cap) + 12;
+ ctrl = memalign(dev->page_size, sizeof(struct nvme_id_ctrl));
+ if (!ctrl)
+ return -ENOMEM;
+
ret = nvme_identify(dev, 0, 1, (dma_addr_t)(long)ctrl);
- if (ret)
+ if (ret) {
+ free(ctrl);
return -EIO;
+ }
dev->nn = le32_to_cpu(ctrl->nn);
dev->vwc = ctrl->vwc;
@@ -621,6 +626,7 @@
static int nvme_get_info_from_identify(struct nvme_dev *dev)
dev->max_transfer_shift = 20;
}
+ free(ctrl);
return 0;
}
@@ -661,16 +667,21 @@
static int nvme_blk_probe(struct udevice *udev)
struct blk_desc *desc = dev_get_uclass_platdata(udev);
struct nvme_ns *ns = dev_get_priv(udev);
u8 flbas;
- ALLOC_CACHE_ALIGN_BUFFER(char, buf, sizeof(struct nvme_id_ns));
- struct nvme_id_ns *id = (struct nvme_id_ns *)buf;
struct pci_child_platdata *pplat;
+ struct nvme_id_ns *id;
+
+ id = memalign(ndev->page_size, sizeof(struct nvme_id_ns));
+ if (!id)
+ return -ENOMEM;
memset(ns, 0, sizeof(*ns));
ns->dev = ndev;
/* extract the namespace id from the block device name */
ns->ns_id = trailing_strtol(udev->name) + 1;
- if (nvme_identify(ndev, ns->ns_id, 0, (dma_addr_t)(long)id))
+ if (nvme_identify(ndev, ns->ns_id, 0, (dma_addr_t)(long)id)) {
+ free(id);
return -EIO;
+ }
memcpy(&ns->eui64, &id->eui64, sizeof(id->eui64));
flbas = id->flbas & NVME_NS_FLBAS_LBA_MASK;
@@ -689,6 +700,7 @@
static int nvme_blk_probe(struct udevice *udev)
memcpy(desc->product, ndev->serial, sizeof(ndev->serial));
memcpy(desc->revision, ndev->firmware_rev, sizeof(ndev->firmware_rev));
+ free(id);
return 0;
}
--
2.22.GIT
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment