aboutsummaryrefslogtreecommitdiff
path: root/drivers/nvme/nvme.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/nvme/nvme.c')
-rw-r--r--drivers/nvme/nvme.c86
1 files changed, 26 insertions, 60 deletions
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
index 3c529a2fce..1d56517e99 100644
--- a/drivers/nvme/nvme.c
+++ b/drivers/nvme/nvme.c
@@ -12,7 +12,6 @@
#include <log.h>
#include <malloc.h>
#include <memalign.h>
-#include <pci.h>
#include <time.h>
#include <dm/device-internal.h>
#include <linux/compat.h>
@@ -28,33 +27,6 @@
#define IO_TIMEOUT 30
#define MAX_PRP_POOL 512
-enum nvme_queue_id {
- NVME_ADMIN_Q,
- NVME_IO_Q,
- NVME_Q_NUM,
-};
-
-/*
- * An NVM Express queue. Each device has at least two (one for admin
- * commands and one for I/O commands).
- */
-struct nvme_queue {
- struct nvme_dev *dev;
- struct nvme_command *sq_cmds;
- struct nvme_completion *cqes;
- wait_queue_head_t sq_full;
- u32 __iomem *q_db;
- u16 q_depth;
- s16 cq_vector;
- u16 sq_head;
- u16 sq_tail;
- u16 cq_head;
- u16 qid;
- u8 cq_phase;
- u8 cqe_seen;
- unsigned long cmdid_data[];
-};
-
static int nvme_wait_ready(struct nvme_dev *dev, bool enabled)
{
u32 bit = enabled ? NVME_CSTS_RDY : 0;
@@ -168,12 +140,19 @@ static u16 nvme_read_completion_status(struct nvme_queue *nvmeq, u16 index)
*/
static void nvme_submit_cmd(struct nvme_queue *nvmeq, struct nvme_command *cmd)
{
+ struct nvme_ops *ops;
u16 tail = nvmeq->sq_tail;
memcpy(&nvmeq->sq_cmds[tail], cmd, sizeof(*cmd));
flush_dcache_range((ulong)&nvmeq->sq_cmds[tail],
(ulong)&nvmeq->sq_cmds[tail] + sizeof(*cmd));
+ ops = (struct nvme_ops *)nvmeq->dev->udev->driver->ops;
+ if (ops && ops->submit_cmd) {
+ ops->submit_cmd(nvmeq, cmd);
+ return;
+ }
+
if (++tail == nvmeq->q_depth)
tail = 0;
writel(tail, nvmeq->q_db);
@@ -184,6 +163,7 @@ static int nvme_submit_sync_cmd(struct nvme_queue *nvmeq,
struct nvme_command *cmd,
u32 *result, unsigned timeout)
{
+ struct nvme_ops *ops;
u16 head = nvmeq->cq_head;
u16 phase = nvmeq->cq_phase;
u16 status;
@@ -204,6 +184,10 @@ static int nvme_submit_sync_cmd(struct nvme_queue *nvmeq,
return -ETIMEDOUT;
}
+ ops = (struct nvme_ops *)nvmeq->dev->udev->driver->ops;
+ if (ops && ops->complete_cmd)
+ ops->complete_cmd(nvmeq, cmd);
+
status >>= 1;
if (status) {
printf("ERROR: status = %x, phase = %d, head = %d\n",
@@ -244,6 +228,7 @@ static int nvme_submit_admin_cmd(struct nvme_dev *dev, struct nvme_command *cmd,
static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev,
int qid, int depth)
{
+ struct nvme_ops *ops;
struct nvme_queue *nvmeq = malloc(sizeof(*nvmeq));
if (!nvmeq)
return NULL;
@@ -269,6 +254,10 @@ static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev,
dev->queue_count++;
dev->queues[qid] = nvmeq;
+ ops = (struct nvme_ops *)dev->udev->driver->ops;
+ if (ops && ops->setup_queue)
+ ops->setup_queue(nvmeq);
+
return nvmeq;
free_queue:
@@ -698,7 +687,6 @@ static int nvme_blk_probe(struct udevice *udev)
struct blk_desc *desc = dev_get_uclass_plat(udev);
struct nvme_ns *ns = dev_get_priv(udev);
u8 flbas;
- struct pci_child_plat *pplat;
struct nvme_id_ns *id;
id = memalign(ndev->page_size, sizeof(struct nvme_id_ns));
@@ -723,8 +711,7 @@ static int nvme_blk_probe(struct udevice *udev)
desc->log2blksz = ns->lba_shift;
desc->blksz = 1 << ns->lba_shift;
desc->bdev = udev;
- pplat = dev_get_parent_plat(udev->parent);
- sprintf(desc->vendor, "0x%.4x", pplat->vendor);
+ memcpy(desc->vendor, ndev->vendor, sizeof(ndev->vendor));
memcpy(desc->product, ndev->serial, sizeof(ndev->serial));
memcpy(desc->revision, ndev->firmware_rev, sizeof(ndev->firmware_rev));
@@ -818,27 +805,14 @@ U_BOOT_DRIVER(nvme_blk) = {
.priv_auto = sizeof(struct nvme_ns),
};
-static int nvme_bind(struct udevice *udev)
-{
- static int ndev_num;
- char name[20];
-
- sprintf(name, "nvme#%d", ndev_num++);
-
- return device_set_name(udev, name);
-}
-
-static int nvme_probe(struct udevice *udev)
+int nvme_init(struct udevice *udev)
{
- int ret;
struct nvme_dev *ndev = dev_get_priv(udev);
struct nvme_id_ns *id;
+ int ret;
- ndev->instance = trailing_strtol(udev->name);
-
+ ndev->udev = udev;
INIT_LIST_HEAD(&ndev->namespaces);
- ndev->bar = dm_pci_map_bar(udev, PCI_BASE_ADDRESS_0,
- PCI_REGION_MEM);
if (readl(&ndev->bar->csts) == -1) {
ret = -ENODEV;
printf("Error: %s: Out of memory!\n", udev->name);
@@ -923,17 +897,9 @@ free_nvme:
return ret;
}
-U_BOOT_DRIVER(nvme) = {
- .name = "nvme",
- .id = UCLASS_NVME,
- .bind = nvme_bind,
- .probe = nvme_probe,
- .priv_auto = sizeof(struct nvme_dev),
-};
-
-struct pci_device_id nvme_supported[] = {
- { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, ~0) },
- {}
-};
+int nvme_shutdown(struct udevice *udev)
+{
+ struct nvme_dev *ndev = dev_get_priv(udev);
-U_BOOT_PCI_DEVICE(nvme, nvme_supported);
+ return nvme_disable_ctrl(ndev);
+}