[PATCH 1/2] nvme: Add 'partial_nid' quirk
hare at kernel.org
hare at kernel.org
Mon Apr 14 02:09:58 PDT 2025
From: Hannes Reinecke <hare at kernel.org>
Add a quirk to handle NVMe devices for which not all NID values are unique,
and return a match from nvme_subsys_check_duplicate_ids() once the first
matching NID value is found.
Signed-off-by: Hannes Reinecke <hare at kernel.org>
---
drivers/nvme/host/core.c | 28 ++++++++++++++++++++++------
drivers/nvme/host/nvme.h | 5 +++++
2 files changed, 27 insertions(+), 6 deletions(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 870314c52107..9e6f4037f33f 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -3576,18 +3576,30 @@ static int nvme_subsys_check_duplicate_ids(struct nvme_subsystem *subsys,
bool has_nguid = memchr_inv(ids->nguid, 0, sizeof(ids->nguid));
bool has_eui64 = memchr_inv(ids->eui64, 0, sizeof(ids->eui64));
struct nvme_ns_head *h;
+ bool match_nid = false;
lockdep_assert_held(&subsys->lock);
list_for_each_entry(h, &subsys->nsheads, entry) {
- if (has_uuid && uuid_equal(&ids->uuid, &h->ids.uuid))
- return -EINVAL;
- if (has_nguid &&
- memcmp(&ids->nguid, &h->ids.nguid, sizeof(ids->nguid)) == 0)
- return -EINVAL;
+ if (has_uuid) {
+ if (uuid_equal(&ids->uuid, &h->ids.uuid))
+ return -EINVAL;
+ match_nid = true;
+ }
+ if (has_nguid) {
+ if (memcmp(&ids->nguid, &h->ids.nguid, sizeof(ids->nguid)) == 0) {
+ if (match_nid)
+ return -ENOTUNIQ;
+ return -EINVAL;
+ }
+ match_nid = true;
+ }
if (has_eui64 &&
- memcmp(&ids->eui64, &h->ids.eui64, sizeof(ids->eui64)) == 0)
+ memcmp(&ids->eui64, &h->ids.eui64, sizeof(ids->eui64)) == 0) {
+ if (match_nid)
+ return -ENOTUNIQ;
return -EINVAL;
+ }
}
return 0;
@@ -3752,6 +3764,8 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info)
int ret;
ret = nvme_global_check_duplicate_ids(ctrl->subsys, &info->ids);
+ if (ret == -ENOTUNIQ && ctrl->quirks & NVME_QUIRK_PARTIAL_NID)
+ ret = 0;
if (ret) {
/*
* We've found two different namespaces on two different
@@ -3793,6 +3807,8 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info)
head = nvme_find_ns_head(ctrl, info->nsid);
if (!head) {
ret = nvme_subsys_check_duplicate_ids(ctrl->subsys, &info->ids);
+ if (ret == -ENOTUNIQ && ctrl->quirks & NVME_QUIRK_PARTIAL_NID)
+ ret = 0;
if (ret) {
dev_err(ctrl->device,
"duplicate IDs in subsystem for nsid %d\n",
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 740ec758712f..8b386fcffa01 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -178,6 +178,11 @@ enum nvme_quirks {
* Align dma pool segment size to 512 bytes
*/
NVME_QUIRK_DMAPOOL_ALIGN_512 = (1 << 22),
+
+ /*
+ * Not all namespace identifiers are unique
+ */
+ NVME_QUIRK_PARTIAL_NID = (1 << 23),
};
/*
--
2.35.3
More information about the Linux-nvme
mailing list