Merge tag 'dma-mapping-5.20-2022-08-06' of git://git.infradead.org/users/hch/dma...
[sfrench/cifs-2.6.git] / drivers / nvme / host / core.c
index 2cb6e58e4e8f2eebfe11c3ffd08a5bbf12952fe0..af367b22871b1f71ae803165d3978d1f87f1f800 100644 (file)
 
 #define NVME_MINORS            (1U << MINORBITS)
 
+struct nvme_ns_info {
+       struct nvme_ns_ids ids;
+       u32 nsid;
+       __le32 anagrpid;
+       bool is_shared;
+       bool is_readonly;
+       bool is_ready;
+};
+
 unsigned int admin_timeout = 60;
 module_param(admin_timeout, uint, 0644);
 MODULE_PARM_DESC(admin_timeout, "timeout in seconds for admin commands");
@@ -1342,8 +1351,8 @@ static int nvme_process_ns_desc(struct nvme_ctrl *ctrl, struct nvme_ns_ids *ids,
        }
 }
 
-static int nvme_identify_ns_descs(struct nvme_ctrl *ctrl, unsigned nsid,
-               struct nvme_ns_ids *ids)
+static int nvme_identify_ns_descs(struct nvme_ctrl *ctrl,
+               struct nvme_ns_info *info)
 {
        struct nvme_command c = { };
        bool csi_seen = false;
@@ -1356,7 +1365,7 @@ static int nvme_identify_ns_descs(struct nvme_ctrl *ctrl, unsigned nsid,
                return 0;
 
        c.identify.opcode = nvme_admin_identify;
-       c.identify.nsid = cpu_to_le32(nsid);
+       c.identify.nsid = cpu_to_le32(info->nsid);
        c.identify.cns = NVME_ID_CNS_NS_DESC_LIST;
 
        data = kzalloc(NVME_IDENTIFY_DATA_SIZE, GFP_KERNEL);
@@ -1368,7 +1377,7 @@ static int nvme_identify_ns_descs(struct nvme_ctrl *ctrl, unsigned nsid,
        if (status) {
                dev_warn(ctrl->device,
                        "Identify Descriptors failed (nsid=%u, status=0x%x)\n",
-                       nsid, status);
+                       info->nsid, status);
                goto free_data;
        }
 
@@ -1378,7 +1387,7 @@ static int nvme_identify_ns_descs(struct nvme_ctrl *ctrl, unsigned nsid,
                if (cur->nidl == 0)
                        break;
 
-               len = nvme_process_ns_desc(ctrl, ids, cur, &csi_seen);
+               len = nvme_process_ns_desc(ctrl, &info->ids, cur, &csi_seen);
                if (len < 0)
                        break;
 
@@ -1387,7 +1396,7 @@ static int nvme_identify_ns_descs(struct nvme_ctrl *ctrl, unsigned nsid,
 
        if (nvme_multi_css(ctrl) && !csi_seen) {
                dev_warn(ctrl->device, "Command set not reported for nsid:%d\n",
-                        nsid);
+                        info->nsid);
                status = -EINVAL;
        }
 
@@ -1397,7 +1406,7 @@ free_data:
 }
 
 static int nvme_identify_ns(struct nvme_ctrl *ctrl, unsigned nsid,
-                       struct nvme_ns_ids *ids, struct nvme_id_ns **id)
+                       struct nvme_id_ns **id)
 {
        struct nvme_command c = { };
        int error;
@@ -1420,51 +1429,66 @@ static int nvme_identify_ns(struct nvme_ctrl *ctrl, unsigned nsid,
        error = NVME_SC_INVALID_NS | NVME_SC_DNR;
        if ((*id)->ncap == 0) /* namespace not allocated or attached */
                goto out_free_id;
+       return 0;
+
+out_free_id:
+       kfree(*id);
+       return error;
+}
 
+static int nvme_ns_info_from_identify(struct nvme_ctrl *ctrl,
+               struct nvme_ns_info *info)
+{
+       struct nvme_ns_ids *ids = &info->ids;
+       struct nvme_id_ns *id;
+       int ret;
 
+       ret = nvme_identify_ns(ctrl, info->nsid, &id);
+       if (ret)
+               return ret;
+       info->anagrpid = id->anagrpid;
+       info->is_shared = id->nmic & NVME_NS_NMIC_SHARED;
+       info->is_readonly = id->nsattr & NVME_NS_ATTR_RO;
+       info->is_ready = true;
        if (ctrl->quirks & NVME_QUIRK_BOGUS_NID) {
                dev_info(ctrl->device,
                         "Ignoring bogus Namespace Identifiers\n");
        } else {
                if (ctrl->vs >= NVME_VS(1, 1, 0) &&
                    !memchr_inv(ids->eui64, 0, sizeof(ids->eui64)))
-                       memcpy(ids->eui64, (*id)->eui64, sizeof(ids->eui64));
+                       memcpy(ids->eui64, id->eui64, sizeof(ids->eui64));
                if (ctrl->vs >= NVME_VS(1, 2, 0) &&
                    !memchr_inv(ids->nguid, 0, sizeof(ids->nguid)))
-                       memcpy(ids->nguid, (*id)->nguid, sizeof(ids->nguid));
+                       memcpy(ids->nguid, id->nguid, sizeof(ids->nguid));
        }
-
+       kfree(id);
        return 0;
-
-out_free_id:
-       kfree(*id);
-       return error;
 }
 
-static int nvme_identify_ns_cs_indep(struct nvme_ctrl *ctrl, unsigned nsid,
-                       struct nvme_id_ns_cs_indep **id)
+static int nvme_ns_info_from_id_cs_indep(struct nvme_ctrl *ctrl,
+               struct nvme_ns_info *info)
 {
+       struct nvme_id_ns_cs_indep *id;
        struct nvme_command c = {
                .identify.opcode        = nvme_admin_identify,
-               .identify.nsid          = cpu_to_le32(nsid),
+               .identify.nsid          = cpu_to_le32(info->nsid),
                .identify.cns           = NVME_ID_CNS_NS_CS_INDEP,
        };
        int ret;
 
-       *id = kmalloc(sizeof(**id), GFP_KERNEL);
-       if (!*id)
+       id = kmalloc(sizeof(*id), GFP_KERNEL);
+       if (!id)
                return -ENOMEM;
 
-       ret = nvme_submit_sync_cmd(ctrl->admin_q, &c, *id, sizeof(**id));
-       if (ret) {
-               dev_warn(ctrl->device,
-                        "Identify namespace (CS independent) failed (%d)\n",
-                        ret);
-               kfree(*id);
-               return ret;
+       ret = nvme_submit_sync_cmd(ctrl->admin_q, &c, id, sizeof(*id));
+       if (!ret) {
+               info->anagrpid = id->anagrpid;
+               info->is_shared = id->nmic & NVME_NS_NMIC_SHARED;
+               info->is_readonly = id->nsattr & NVME_NS_ATTR_RO;
+               info->is_ready = id->nstat & NVME_NSTAT_NRDY;
        }
-
-       return 0;
+       kfree(id);
+       return ret;
 }
 
 static int nvme_features(struct nvme_ctrl *dev, u8 op, unsigned int fid,
@@ -1888,6 +1912,11 @@ static void nvme_update_disk_info(struct gendisk *disk,
                                           ns->ctrl->max_zeroes_sectors);
 }
 
+static bool nvme_ns_is_readonly(struct nvme_ns *ns, struct nvme_ns_info *info)
+{
+       return info->is_readonly || test_bit(NVME_NS_FORCE_RO, &ns->flags);
+}
+
 static inline bool nvme_first_scan(struct gendisk *disk)
 {
        /* nvme_alloc_ns() scans the disk prior to adding it */
@@ -1925,12 +1954,44 @@ static void nvme_set_chunk_sectors(struct nvme_ns *ns, struct nvme_id_ns *id)
        blk_queue_chunk_sectors(ns->queue, iob);
 }
 
-static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_id_ns *id)
+static int nvme_update_ns_info_generic(struct nvme_ns *ns,
+               struct nvme_ns_info *info)
 {
-       unsigned lbaf = nvme_lbaf_index(id->flbas);
+       blk_mq_freeze_queue(ns->disk->queue);
+       nvme_set_queue_limits(ns->ctrl, ns->queue);
+       set_disk_ro(ns->disk, nvme_ns_is_readonly(ns, info));
+       blk_mq_unfreeze_queue(ns->disk->queue);
+
+       if (nvme_ns_head_multipath(ns->head)) {
+               blk_mq_freeze_queue(ns->head->disk->queue);
+               set_disk_ro(ns->head->disk, nvme_ns_is_readonly(ns, info));
+               nvme_mpath_revalidate_paths(ns);
+               blk_stack_limits(&ns->head->disk->queue->limits,
+                                &ns->queue->limits, 0);
+               ns->head->disk->flags |= GENHD_FL_HIDDEN;
+               blk_mq_unfreeze_queue(ns->head->disk->queue);
+       }
+
+       /* Hide the block-interface for these devices */
+       ns->disk->flags |= GENHD_FL_HIDDEN;
+       set_bit(NVME_NS_READY, &ns->flags);
+
+       return 0;
+}
+
+static int nvme_update_ns_info_block(struct nvme_ns *ns,
+               struct nvme_ns_info *info)
+{
+       struct nvme_id_ns *id;
+       unsigned lbaf;
        int ret;
 
+       ret = nvme_identify_ns(ns->ctrl, info->nsid, &id);
+       if (ret)
+               return ret;
+
        blk_mq_freeze_queue(ns->disk->queue);
+       lbaf = nvme_lbaf_index(id->flbas);
        ns->lba_shift = id->lbaf[lbaf].ds;
        nvme_set_queue_limits(ns->ctrl, ns->queue);
 
@@ -1940,36 +2001,35 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_id_ns *id)
 
        if (ns->head->ids.csi == NVME_CSI_ZNS) {
                ret = nvme_update_zone_info(ns, lbaf);
-               if (ret)
-                       goto out_unfreeze;
+               if (ret) {
+                       blk_mq_unfreeze_queue(ns->disk->queue);
+                       goto out;
+               }
        }
 
-       set_disk_ro(ns->disk, (id->nsattr & NVME_NS_ATTR_RO) ||
-               test_bit(NVME_NS_FORCE_RO, &ns->flags));
+       set_disk_ro(ns->disk, nvme_ns_is_readonly(ns, info));
        set_bit(NVME_NS_READY, &ns->flags);
        blk_mq_unfreeze_queue(ns->disk->queue);
 
        if (blk_queue_is_zoned(ns->queue)) {
                ret = nvme_revalidate_zones(ns);
                if (ret && !nvme_first_scan(ns->disk))
-                       return ret;
+                       goto out;
        }
 
        if (nvme_ns_head_multipath(ns->head)) {
                blk_mq_freeze_queue(ns->head->disk->queue);
                nvme_update_disk_info(ns->head->disk, ns, id);
-               set_disk_ro(ns->head->disk,
-                           (id->nsattr & NVME_NS_ATTR_RO) ||
-                                   test_bit(NVME_NS_FORCE_RO, &ns->flags));
+               set_disk_ro(ns->head->disk, nvme_ns_is_readonly(ns, info));
                nvme_mpath_revalidate_paths(ns);
                blk_stack_limits(&ns->head->disk->queue->limits,
                                 &ns->queue->limits, 0);
                disk_update_readahead(ns->head->disk);
                blk_mq_unfreeze_queue(ns->head->disk->queue);
        }
-       return 0;
 
-out_unfreeze:
+       ret = 0;
+out:
        /*
         * If probing fails due an unsupported feature, hide the block device,
         * but still allow other access.
@@ -1979,10 +2039,31 @@ out_unfreeze:
                set_bit(NVME_NS_READY, &ns->flags);
                ret = 0;
        }
-       blk_mq_unfreeze_queue(ns->disk->queue);
+       kfree(id);
        return ret;
 }
 
+static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_ns_info *info)
+{
+       switch (info->ids.csi) {
+       case NVME_CSI_ZNS:
+               if (!IS_ENABLED(CONFIG_BLK_DEV_ZONED)) {
+                       dev_info(ns->ctrl->device,
+       "block device for nsid %u not supported without CONFIG_BLK_DEV_ZONED\n",
+                               info->nsid);
+                       return nvme_update_ns_info_generic(ns, info);
+               }
+               return nvme_update_ns_info_block(ns, info);
+       case NVME_CSI_NVM:
+               return nvme_update_ns_info_block(ns, info);
+       default:
+               dev_info(ns->ctrl->device,
+                       "block device for nsid %u not supported (csi %u)\n",
+                       info->nsid, info->ids.csi);
+               return nvme_update_ns_info_generic(ns, info);
+       }
+}
+
 static char nvme_pr_type(enum pr_type type)
 {
        switch (type) {
@@ -3912,7 +3993,7 @@ static int nvme_add_ns_cdev(struct nvme_ns *ns)
 }
 
 static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl,
-               unsigned nsid, struct nvme_ns_ids *ids, bool is_shared)
+               struct nvme_ns_info *info)
 {
        struct nvme_ns_head *head;
        size_t size = sizeof(*head);
@@ -3934,9 +4015,9 @@ static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl,
        if (ret)
                goto out_ida_remove;
        head->subsys = ctrl->subsys;
-       head->ns_id = nsid;
-       head->ids = *ids;
-       head->shared = is_shared;
+       head->ns_id = info->nsid;
+       head->ids = info->ids;
+       head->shared = info->is_shared;
        kref_init(&head->ref);
 
        if (head->ids.csi) {
@@ -3993,54 +4074,54 @@ static int nvme_global_check_duplicate_ids(struct nvme_subsystem *this,
        return ret;
 }
 
-static int nvme_init_ns_head(struct nvme_ns *ns, unsigned nsid,
-               struct nvme_ns_ids *ids, bool is_shared)
+static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info)
 {
        struct nvme_ctrl *ctrl = ns->ctrl;
        struct nvme_ns_head *head = NULL;
        int ret;
 
-       ret = nvme_global_check_duplicate_ids(ctrl->subsys, ids);
+       ret = nvme_global_check_duplicate_ids(ctrl->subsys, &info->ids);
        if (ret) {
                dev_err(ctrl->device,
-                       "globally duplicate IDs for nsid %d\n", nsid);
+                       "globally duplicate IDs for nsid %d\n", info->nsid);
                nvme_print_device_info(ctrl);
                return ret;
        }
 
        mutex_lock(&ctrl->subsys->lock);
-       head = nvme_find_ns_head(ctrl, nsid);
+       head = nvme_find_ns_head(ctrl, info->nsid);
        if (!head) {
-               ret = nvme_subsys_check_duplicate_ids(ctrl->subsys, ids);
+               ret = nvme_subsys_check_duplicate_ids(ctrl->subsys, &info->ids);
                if (ret) {
                        dev_err(ctrl->device,
                                "duplicate IDs in subsystem for nsid %d\n",
-                               nsid);
+                               info->nsid);
                        goto out_unlock;
                }
-               head = nvme_alloc_ns_head(ctrl, nsid, ids, is_shared);
+               head = nvme_alloc_ns_head(ctrl, info);
                if (IS_ERR(head)) {
                        ret = PTR_ERR(head);
                        goto out_unlock;
                }
        } else {
                ret = -EINVAL;
-               if (!is_shared || !head->shared) {
+               if (!info->is_shared || !head->shared) {
                        dev_err(ctrl->device,
-                               "Duplicate unshared namespace %d\n", nsid);
+                               "Duplicate unshared namespace %d\n",
+                               info->nsid);
                        goto out_put_ns_head;
                }
-               if (!nvme_ns_ids_equal(&head->ids, ids)) {
+               if (!nvme_ns_ids_equal(&head->ids, &info->ids)) {
                        dev_err(ctrl->device,
                                "IDs don't match for shared namespace %d\n",
-                                       nsid);
+                                       info->nsid);
                        goto out_put_ns_head;
                }
 
                if (!multipath && !list_empty(&head->list)) {
                        dev_warn(ctrl->device,
                                "Found shared namespace %d, but multipathing not supported.\n",
-                               nsid);
+                               info->nsid);
                        dev_warn_once(ctrl->device,
                                "Support for shared namespaces without CONFIG_NVME_MULTIPATH is deprecated and will be removed in Linux 6.0\n.");
                }
@@ -4094,20 +4175,15 @@ static void nvme_ns_add_to_ctrl_list(struct nvme_ns *ns)
        list_add(&ns->list, &ns->ctrl->namespaces);
 }
 
-static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid,
-               struct nvme_ns_ids *ids)
+static void nvme_alloc_ns(struct nvme_ctrl *ctrl, struct nvme_ns_info *info)
 {
        struct nvme_ns *ns;
        struct gendisk *disk;
-       struct nvme_id_ns *id;
        int node = ctrl->numa_node;
 
-       if (nvme_identify_ns(ctrl, nsid, ids, &id))
-               return;
-
        ns = kzalloc_node(sizeof(*ns), GFP_KERNEL, node);
        if (!ns)
-               goto out_free_id;
+               return;
 
        disk = blk_mq_alloc_disk(ctrl->tagset, ns);
        if (IS_ERR(disk))
@@ -4122,13 +4198,14 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid,
                blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, ns->queue);
 
        blk_queue_flag_set(QUEUE_FLAG_NONROT, ns->queue);
-       if (ctrl->ops->flags & NVME_F_PCI_P2PDMA)
+       if (ctrl->ops->supports_pci_p2pdma &&
+           ctrl->ops->supports_pci_p2pdma(ctrl))
                blk_queue_flag_set(QUEUE_FLAG_PCI_P2PDMA, ns->queue);
 
        ns->ctrl = ctrl;
        kref_init(&ns->kref);
 
-       if (nvme_init_ns_head(ns, nsid, ids, id->nmic & NVME_NS_NMIC_SHARED))
+       if (nvme_init_ns_head(ns, info))
                goto out_cleanup_disk;
 
        /*
@@ -4154,7 +4231,7 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid,
                        ns->head->instance);
        }
 
-       if (nvme_update_ns_info(ns, id))
+       if (nvme_update_ns_info(ns, info))
                goto out_unlink_ns;
 
        down_write(&ctrl->namespaces_rwsem);
@@ -4168,9 +4245,8 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid,
        if (!nvme_ns_head_multipath(ns->head))
                nvme_add_ns_cdev(ns);
 
-       nvme_mpath_add_disk(ns, id->anagrpid);
+       nvme_mpath_add_disk(ns, info->anagrpid);
        nvme_fault_inject_init(&ns->fault_inject, ns->disk->disk_name);
-       kfree(id);
 
        return;
 
@@ -4190,8 +4266,6 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid,
        put_disk(disk);
  out_free_ns:
        kfree(ns);
- out_free_id:
-       kfree(id);
 }
 
 static void nvme_ns_remove(struct nvme_ns *ns)
@@ -4249,29 +4323,21 @@ static void nvme_ns_remove_by_nsid(struct nvme_ctrl *ctrl, u32 nsid)
        }
 }
 
-static void nvme_validate_ns(struct nvme_ns *ns, struct nvme_ns_ids *ids)
+static void nvme_validate_ns(struct nvme_ns *ns, struct nvme_ns_info *info)
 {
-       struct nvme_id_ns *id;
        int ret = NVME_SC_INVALID_NS | NVME_SC_DNR;
 
        if (test_bit(NVME_NS_DEAD, &ns->flags))
                goto out;
 
-       ret = nvme_identify_ns(ns->ctrl, ns->head->ns_id, ids, &id);
-       if (ret)
-               goto out;
-
        ret = NVME_SC_INVALID_NS | NVME_SC_DNR;
-       if (!nvme_ns_ids_equal(&ns->head->ids, ids)) {
+       if (!nvme_ns_ids_equal(&ns->head->ids, &info->ids)) {
                dev_err(ns->ctrl->device,
                        "identifiers changed for nsid %d\n", ns->head->ns_id);
-               goto out_free_id;
+               goto out;
        }
 
-       ret = nvme_update_ns_info(ns, id);
-
-out_free_id:
-       kfree(id);
+       ret = nvme_update_ns_info(ns, info);
 out:
        /*
         * Only remove the namespace if we got a fatal error back from the
@@ -4283,59 +4349,47 @@ out:
                nvme_ns_remove(ns);
 }
 
-static void nvme_validate_or_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
+static void nvme_scan_ns(struct nvme_ctrl *ctrl, unsigned nsid)
 {
-       struct nvme_ns_ids ids = { };
-       struct nvme_id_ns_cs_indep *id;
+       struct nvme_ns_info info = { .nsid = nsid };
        struct nvme_ns *ns;
-       bool ready = true;
 
-       if (nvme_identify_ns_descs(ctrl, nsid, &ids))
+       if (nvme_identify_ns_descs(ctrl, &info))
+               return;
+
+       if (info.ids.csi != NVME_CSI_NVM && !nvme_multi_css(ctrl)) {
+               dev_warn(ctrl->device,
+                       "command set not reported for nsid: %d\n", nsid);
                return;
+       }
 
        /*
-        * Check if the namespace is ready.  If not ignore it, we will get an
-        * AEN once it becomes ready and restart the scan.
+        * If available try to use the Command Set Idependent Identify Namespace
+        * data structure to find all the generic information that is needed to
+        * set up a namespace.  If not fall back to the legacy version.
         */
-       if ((ctrl->cap & NVME_CAP_CRMS_CRIMS) &&
-           !nvme_identify_ns_cs_indep(ctrl, nsid, &id)) {
-               ready = id->nstat & NVME_NSTAT_NRDY;
-               kfree(id);
+       if ((ctrl->cap & NVME_CAP_CRMS_CRIMS) ||
+           (info.ids.csi != NVME_CSI_NVM && info.ids.csi != NVME_CSI_ZNS)) {
+               if (nvme_ns_info_from_id_cs_indep(ctrl, &info))
+                       return;
+       } else {
+               if (nvme_ns_info_from_identify(ctrl, &info))
+                       return;
        }
 
-       if (!ready)
+       /*
+        * Ignore the namespace if it is not ready. We will get an AEN once it
+        * becomes ready and restart the scan.
+        */
+       if (!info.is_ready)
                return;
 
        ns = nvme_find_get_ns(ctrl, nsid);
        if (ns) {
-               nvme_validate_ns(ns, &ids);
+               nvme_validate_ns(ns, &info);
                nvme_put_ns(ns);
-               return;
-       }
-
-       switch (ids.csi) {
-       case NVME_CSI_NVM:
-               nvme_alloc_ns(ctrl, nsid, &ids);
-               break;
-       case NVME_CSI_ZNS:
-               if (!IS_ENABLED(CONFIG_BLK_DEV_ZONED)) {
-                       dev_warn(ctrl->device,
-                               "nsid %u not supported without CONFIG_BLK_DEV_ZONED\n",
-                               nsid);
-                       break;
-               }
-               if (!nvme_multi_css(ctrl)) {
-                       dev_warn(ctrl->device,
-                               "command set not reported for nsid: %d\n",
-                               nsid);
-                       break;
-               }
-               nvme_alloc_ns(ctrl, nsid, &ids);
-               break;
-       default:
-               dev_warn(ctrl->device, "unknown csi %u for nsid %u\n",
-                       ids.csi, nsid);
-               break;
+       } else {
+               nvme_alloc_ns(ctrl, &info);
        }
 }
 
@@ -4391,7 +4445,7 @@ static int nvme_scan_ns_list(struct nvme_ctrl *ctrl)
 
                        if (!nsid)      /* end of the list? */
                                goto out;
-                       nvme_validate_or_alloc_ns(ctrl, nsid);
+                       nvme_scan_ns(ctrl, nsid);
                        while (++prev < nsid)
                                nvme_ns_remove_by_nsid(ctrl, prev);
                }
@@ -4414,7 +4468,7 @@ static void nvme_scan_ns_sequential(struct nvme_ctrl *ctrl)
        kfree(id);
 
        for (i = 1; i <= nn; i++)
-               nvme_validate_or_alloc_ns(ctrl, i);
+               nvme_scan_ns(ctrl, i);
 
        nvme_remove_invalid_namespaces(ctrl, nn);
 }