From mboxrd@z Thu Jan 1 00:00:00 1970 From: Bin Meng Date: Tue, 22 Aug 2017 08:15:14 -0700 Subject: [U-Boot] [PATCH 09/14] nvme: Apply cache operations on the DMA buffers In-Reply-To: <1503414919-30820-1-git-send-email-bmeng.cn@gmail.com> References: <1503414919-30820-1-git-send-email-bmeng.cn@gmail.com> Message-ID: <1503414919-30820-10-git-send-email-bmeng.cn@gmail.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de So far cache operations are only applied on the submission queue and completion queue, but they are missing in other places like identify and block read/write routines. In order to correctly operate on the caches, the DMA buffer passed to identify routine must be allocated properly on the stack with the existing macro ALLOC_CACHE_ALIGN_BUFFER(). Signed-off-by: Bin Meng --- drivers/nvme/nvme.c | 32 +++++++++++++++++++++++++++++--- drivers/nvme/nvme_show.c | 7 +++++-- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c index c545ce7..67f7d75 100644 --- a/drivers/nvme/nvme.c +++ b/drivers/nvme/nvme.c @@ -435,6 +435,7 @@ int nvme_identify(struct nvme_dev *dev, unsigned nsid, u32 page_size = dev->page_size; int offset = dma_addr & (page_size - 1); int length = sizeof(struct nvme_id_ctrl); + int ret; memset(&c, 0, sizeof(c)); c.identify.opcode = nvme_admin_identify; @@ -451,7 +452,12 @@ int nvme_identify(struct nvme_dev *dev, unsigned nsid, c.identify.cns = cpu_to_le32(cns); - return nvme_submit_admin_cmd(dev, &c, NULL); + ret = nvme_submit_admin_cmd(dev, &c, NULL); + if (!ret) + invalidate_dcache_range(dma_addr, + dma_addr + sizeof(struct nvme_id_ctrl)); + + return ret; } int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid, @@ -465,6 +471,11 @@ int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid, c.features.prp1 = cpu_to_le64(dma_addr); c.features.fid = cpu_to_le32(fid); + /* + * TODO: add cache invalidate operation when the size of + * the DMA buffer is known + */ + return nvme_submit_admin_cmd(dev, &c, result); } @@ -479,6 +490,11 @@ int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11, c.features.fid = cpu_to_le32(fid); c.features.dword11 = cpu_to_le32(dword11); + /* + * TODO: add cache flush operation when the size of + * the DMA buffer is known + */ + return nvme_submit_admin_cmd(dev, &c, result); } @@ -562,7 +578,8 @@ static int nvme_setup_io_queues(struct nvme_dev *dev) static int nvme_get_info_from_identify(struct nvme_dev *dev) { - struct nvme_id_ctrl buf, *ctrl = &buf; + ALLOC_CACHE_ALIGN_BUFFER(char, buf, sizeof(struct nvme_id_ctrl)); + struct nvme_id_ctrl *ctrl = (struct nvme_id_ctrl *)buf; int ret; int shift = NVME_CAP_MPSMIN(dev->cap) + 12; @@ -627,7 +644,8 @@ 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; - struct nvme_id_ns buf, *id = &buf; + 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; memset(ns, 0, sizeof(*ns)); @@ -672,6 +690,10 @@ 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); + c.rw.opcode = read ? nvme_cmd_read : nvme_cmd_write; c.rw.flags = 0; c.rw.nsid = cpu_to_le32(ns->ns_id); @@ -706,6 +728,10 @@ static ulong nvme_blk_rw(struct udevice *udev, lbaint_t blknr, buffer += lbas << ns->lba_shift; } + if (read) + invalidate_dcache_range((unsigned long)buffer, + (unsigned long)buffer + total_len); + return (total_len - temp_len) >> desc->log2blksz; } diff --git a/drivers/nvme/nvme_show.c b/drivers/nvme/nvme_show.c index 5577e5d..5235138 100644 --- a/drivers/nvme/nvme_show.c +++ b/drivers/nvme/nvme_show.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "nvme.h" @@ -106,8 +107,10 @@ int nvme_print_info(struct udevice *udev) { struct nvme_ns *ns = dev_get_priv(udev); struct nvme_dev *dev = ns->dev; - struct nvme_id_ns buf_ns, *id = &buf_ns; - struct nvme_id_ctrl buf_ctrl, *ctrl = &buf_ctrl; + 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; if (nvme_identify(dev, 0, 1, (dma_addr_t)ctrl)) return -EIO; -- 2.9.2