+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 NXP Semiconductors
* Copyright (C) 2017 Bin Meng <bmeng.cn@gmail.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm/device-internal.h>
#include "nvme.h"
-struct nvme_info *nvme_info;
-
#define NVME_Q_DEPTH 2
#define NVME_AQ_DEPTH 2
#define NVME_SQ_SIZE(depth) (depth * sizeof(struct nvme_command))
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;
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,
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);
}
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);
}
if (result <= 0)
return result;
- if (result < nr_io_queues)
- nr_io_queues = result;
-
dev->max_qid = nr_io_queues;
/* Free previously allocated queues */
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;
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));
ns->dev = ndev;
- ns->ns_id = desc->devnum - ndev->blk_dev_start + 1;
+ /* 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))
return -EIO;
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);
&c, NULL, IO_TIMEOUT);
if (status)
break;
- temp_len -= lbas << ns->lba_shift;
+ temp_len -= (u32)lbas << ns->lba_shift;
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;
}
static int nvme_bind(struct udevice *udev)
{
+ static int ndev_num;
char name[20];
- sprintf(name, "nvme#%d", nvme_info->ndev_num++);
+
+ sprintf(name, "nvme#%d", ndev_num++);
return device_set_name(udev, name);
}
printf("Error: %s: Out of memory!\n", udev->name);
goto free_nvme;
}
- memset(ndev->queues, 0,
- sizeof(NVME_Q_NUM * sizeof(struct nvme_queue *)));
+ memset(ndev->queues, 0, NVME_Q_NUM * sizeof(struct nvme_queue *));
ndev->prp_pool = malloc(MAX_PRP_POOL);
if (!ndev->prp_pool) {
goto free_queue;
nvme_get_info_from_identify(ndev);
- ndev->blk_dev_start = nvme_info->ns_num;
- list_add(&ndev->node, &nvme_info->dev_list);
return 0;