Skip to content

Commit f54f0d0

Browse files
committed
nvme: enhance cns version checking
The number of CNS bits in the command is specific to the nvme spec version compliance. The existing check is not sufficient for possible CNS values the driver uses that may create confusion between host and device, so enhance the check to consider the version and desired CNS value. Reviewed-by: Sagi Grimberg <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Keith Busch <[email protected]>
1 parent 49c234b commit f54f0d0

File tree

1 file changed

+25
-12
lines changed

1 file changed

+25
-12
lines changed

drivers/nvme/host/core.c

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1390,17 +1390,30 @@ static void nvme_update_keep_alive(struct nvme_ctrl *ctrl,
13901390
nvme_start_keep_alive(ctrl);
13911391
}
13921392

1393-
/*
1394-
* In NVMe 1.0 the CNS field was just a binary controller or namespace
1395-
* flag, thus sending any new CNS opcodes has a big chance of not working.
1396-
* Qemu unfortunately had that bug after reporting a 1.1 version compliance
1397-
* (but not for any later version).
1398-
*/
1399-
static bool nvme_ctrl_limited_cns(struct nvme_ctrl *ctrl)
1393+
static bool nvme_id_cns_ok(struct nvme_ctrl *ctrl, u8 cns)
14001394
{
1401-
if (ctrl->quirks & NVME_QUIRK_IDENTIFY_CNS)
1402-
return ctrl->vs < NVME_VS(1, 2, 0);
1403-
return ctrl->vs < NVME_VS(1, 1, 0);
1395+
/*
1396+
* The CNS field occupies a full byte starting with NVMe 1.2
1397+
*/
1398+
if (ctrl->vs >= NVME_VS(1, 2, 0))
1399+
return true;
1400+
1401+
/*
1402+
* NVMe 1.1 expanded the CNS value to two bits, which means values
1403+
* larger than that could get truncated and treated as an incorrect
1404+
* value.
1405+
*
1406+
* Qemu implemented 1.0 behavior for controllers claiming 1.1
1407+
* compliance, so they need to be quirked here.
1408+
*/
1409+
if (ctrl->vs >= NVME_VS(1, 1, 0) &&
1410+
!(ctrl->quirks & NVME_QUIRK_IDENTIFY_CNS))
1411+
return cns <= 3;
1412+
1413+
/*
1414+
* NVMe 1.0 used a single bit for the CNS value.
1415+
*/
1416+
return cns <= 1;
14041417
}
14051418

14061419
static int nvme_identify_ctrl(struct nvme_ctrl *dev, struct nvme_id_ctrl **id)
@@ -3104,7 +3117,7 @@ static int nvme_init_non_mdts_limits(struct nvme_ctrl *ctrl)
31043117
ctrl->max_zeroes_sectors = 0;
31053118

31063119
if (ctrl->subsys->subtype != NVME_NQN_NVME ||
3107-
nvme_ctrl_limited_cns(ctrl) ||
3120+
!nvme_id_cns_ok(ctrl, NVME_ID_CNS_CS_CTRL) ||
31083121
test_bit(NVME_CTRL_SKIP_ID_CNS_CS, &ctrl->flags))
31093122
return 0;
31103123

@@ -4200,7 +4213,7 @@ static void nvme_scan_work(struct work_struct *work)
42004213
}
42014214

42024215
mutex_lock(&ctrl->scan_lock);
4203-
if (nvme_ctrl_limited_cns(ctrl)) {
4216+
if (!nvme_id_cns_ok(ctrl, NVME_ID_CNS_NS_ACTIVE_LIST)) {
42044217
nvme_scan_ns_sequential(ctrl);
42054218
} else {
42064219
/*

0 commit comments

Comments
 (0)