]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
nvme: Skip block device creation for inactive namespaces
authorBin Meng <bmeng.cn@gmail.com>
Tue, 22 Jun 2021 13:16:18 +0000 (21:16 +0800)
committerBin Meng <bmeng.cn@gmail.com>
Wed, 23 Jun 2021 09:21:14 +0000 (17:21 +0800)
At present for each namespace there is a block device created for it.
There is no issue if the number of supported namespaces reported from
the NVMe device is only 1.

Since QEMU commit 7f0f1acedf15 ("hw/block/nvme: support multiple namespaces"),
the number of supported namespaces reported has been changed from 1
to 256, but not all of them are active namespaces. The actual active
one depends on the QEMU command line parameters. A common case is
that namespace 1 being active and all other 255 being inactive.

If a namespace is inactive, the namespace identify command returns a
zero filled data structure. We can use field NSZE (namespace size) to
decide whether a block device should be created for it.

Reported-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
drivers/nvme/nvme.c

index afb1a7ea978cb33113a0c1352cdd8177fedbc7a7..acf337a58aa53d732aa39c6f77bafddaf4b522ff 100644 (file)
@@ -834,6 +834,7 @@ static int nvme_probe(struct udevice *udev)
 {
        int ret;
        struct nvme_dev *ndev = dev_get_priv(udev);
+       struct nvme_id_ns *id;
 
        ndev->instance = trailing_strtol(udev->name);
 
@@ -879,10 +880,27 @@ static int nvme_probe(struct udevice *udev)
        nvme_get_info_from_identify(ndev);
 
        /* Create a blk device for each namespace */
+
+       id = memalign(ndev->page_size, sizeof(struct nvme_id_ns));
+       if (!id) {
+               ret = -ENOMEM;
+               goto free_queue;
+       }
+
        for (int i = 0; i < ndev->nn; i++) {
                struct udevice *ns_udev;
                char name[20];
 
+               memset(id, 0, sizeof(*id));
+               if (nvme_identify(ndev, i + 1, 0, (dma_addr_t)(long)id)) {
+                       ret = -EIO;
+                       goto free_id;
+               }
+
+               /* skip inactive namespace */
+               if (!id->nsze)
+                       continue;
+
                /*
                 * Encode the namespace id to the device name so that
                 * we can extract it when doing the probe.
@@ -893,11 +911,14 @@ static int nvme_probe(struct udevice *udev)
                ret = blk_create_devicef(udev, "nvme-blk", name, IF_TYPE_NVME,
                                         -1, 512, 0, &ns_udev);
                if (ret)
-                       goto free_queue;
+                       goto free_id;
        }
 
+       free(id);
        return 0;
 
+free_id:
+       free(id);
 free_queue:
        free((void *)ndev->queues);
 free_nvme: