aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDaniel Verkamp <daniel@drv.nu>2017-02-23 23:27:53 -0700
committerKevin O'Connor <kevin@koconnor.net>2017-03-02 09:45:45 -0500
commitf21e3044a6b8c2195fb243aeb20b3511569e120a (patch)
treedc43920934d66e6dc7f378b2c0628be482cfff11 /src
parent6bc4164cc8570ed3140d34080e38878adce13593 (diff)
downloadseabios-f21e3044a6b8c2195fb243aeb20b3511569e120a.tar.gz
nvme: support NVMe 1.0 controllers
Rather than using the Identify command with CNS 01b (GET_NS_LIST), which was added in NVMe 1.1, we can just enumerate all of the possible namespace IDs. The relevant part of the NVMe spec reads: Namespaces shall be allocated in order (starting with 1) and packed sequentially. Since the previously-used GET_NS_LIST only returns active namespaces, we also need a check in nvme_probe_ns() to ensure that inactive namespaces are not reported as boot devices. This can be accomplished by checking for non-zero block count - the spec indicates that Identify Namespace for an inactive namespace ID will return all zeroes. This should have no impact on the QEMU NVMe device model, since it always reports exactly one namespace (NSID 1). Signed-off-by: Daniel Verkamp <daniel@drv.nu>
Diffstat (limited to 'src')
-rw-r--r--src/hw/nvme.c39
1 files changed, 6 insertions, 33 deletions
diff --git a/src/hw/nvme.c b/src/hw/nvme.c
index 31edf292..c709a3ae 100644
--- a/src/hw/nvme.c
+++ b/src/hw/nvme.c
@@ -218,13 +218,6 @@ nvme_admin_identify_ctrl(struct nvme_ctrl *ctrl)
return &nvme_admin_identify(ctrl, NVME_ADMIN_IDENTIFY_CNS_ID_CTRL, 0)->ctrl;
}
-static struct nvme_identify_ns_list *
-nvme_admin_identify_get_ns_list(struct nvme_ctrl *ctrl)
-{
- return &nvme_admin_identify(ctrl, NVME_ADMIN_IDENTIFY_CNS_GET_NS_LIST,
- 0)->ns_list;
-}
-
static struct nvme_identify_ns *
nvme_admin_identify_ns(struct nvme_ctrl *ctrl, u32 ns_id)
{
@@ -253,6 +246,10 @@ nvme_probe_ns(struct nvme_ctrl *ctrl, struct nvme_namespace *ns, u32 ns_id)
}
ns->lba_count = id->nsze;
+ if (!ns->lba_count) {
+ dprintf(2, "NVMe NS %u is inactive.\n", ns_id);
+ goto free_buffer;
+ }
struct nvme_lba_format *fmt = &id->lbaf[current_lba_format];
@@ -493,29 +490,10 @@ nvme_controller_enable(struct nvme_ctrl *ctrl)
if (!ctrl->ns) goto out_of_memory;
memset(ctrl->ns, 0, sizeof(*ctrl->ns) * ctrl->ns_count);
- struct nvme_identify_ns_list *ns_list = nvme_admin_identify_get_ns_list(ctrl);
- if (!ns_list) {
- dprintf(2, "NVMe couldn't get namespace list.\n");
- goto failed;
- }
-
/* Populate namespace IDs */
int ns_idx;
- for (ns_idx = 0;
- ns_idx < ARRAY_SIZE(ns_list->ns_id)
- && ns_idx < ctrl->ns_count
- && ns_list->ns_id[ns_idx];
- ns_idx++) {
- nvme_probe_ns(ctrl, &ctrl->ns[ns_idx], ns_list->ns_id[ns_idx]);
- }
-
- free(ns_list);
-
- /* If for some reason the namespace list gives us fewer namespaces, we just
- go along. */
- if (ns_idx != ctrl->ns_count) {
- dprintf(2, "NVMe namespace list has only %u namespaces?\n", ns_idx);
- ctrl->ns_count = ns_idx;
+ for (ns_idx = 0; ns_idx < ctrl->ns_count; ns_idx++) {
+ nvme_probe_ns(ctrl, &ctrl->ns[ns_idx], ns_idx + 1);
}
dprintf(3, "NVMe initialization complete!\n");
@@ -545,11 +523,6 @@ nvme_controller_setup(void *opaque)
version >> 16, (version >> 8) & 0xFF, version & 0xFF);
dprintf(3, " Capabilities %016llx\n", reg->cap);
- if (version < 0x00010100U) {
- dprintf(3, "Need at least 1.1.0! Skipping.\n");
- return;
- }
-
if (~reg->cap & NVME_CAP_CSS_NVME) {
dprintf(3, "Controller doesn't speak NVMe command set. Skipping.\n");
return;