Skip to content

Commit b8e0808

Browse files
dmcleranMatthew Wilcox
authored andcommitted
NVMe: Fix START_STOP_UNIT Scsi->NVMe translation.
This patch contains several fixes for Scsi START_STOP_UNIT. The previous code did not account for signed vs. unsigned arithmetic which resulted in an invalid lowest power state caculation when the device only supports 1 power state. The code for Power Condition == 2 (Idle) was not following the spec. The spec calls for setting the device to specific power states, depending upon Power Condition Modifier, without accounting for the number of power states supported by the device. The code for Power Condition == 3 (Standby) was using a hard-coded '0' which is replaced with the macro POWER_STATE_0. Signed-off-by: Dan McLeran <[email protected]> Reviewed-by: Vishal Verma <[email protected]> Signed-off-by: Matthew Wilcox <[email protected]>
1 parent ef351b9 commit b8e0808

File tree

1 file changed

+6
-7
lines changed

1 file changed

+6
-7
lines changed

drivers/block/nvme-scsi.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1476,7 +1476,7 @@ static int nvme_trans_power_state(struct nvme_ns *ns, struct sg_io_hdr *hdr,
14761476
goto out_dma;
14771477
}
14781478
id_ctrl = mem;
1479-
lowest_pow_st = id_ctrl->npss - 1;
1479+
lowest_pow_st = max(POWER_STATE_0, (int)(id_ctrl->npss - 1));
14801480

14811481
switch (pc) {
14821482
case NVME_POWER_STATE_START_VALID:
@@ -1493,20 +1493,19 @@ static int nvme_trans_power_state(struct nvme_ns *ns, struct sg_io_hdr *hdr,
14931493
break;
14941494
case NVME_POWER_STATE_IDLE:
14951495
/* Action unspecified if POWER CONDITION MODIFIER != [0,1,2] */
1496-
/* min of desired state and (lps-1) because lps is STOP */
14971496
if (pcmod == 0x0)
1498-
ps_desired = min(POWER_STATE_1, (lowest_pow_st - 1));
1497+
ps_desired = POWER_STATE_1;
14991498
else if (pcmod == 0x1)
1500-
ps_desired = min(POWER_STATE_2, (lowest_pow_st - 1));
1499+
ps_desired = POWER_STATE_2;
15011500
else if (pcmod == 0x2)
1502-
ps_desired = min(POWER_STATE_3, (lowest_pow_st - 1));
1501+
ps_desired = POWER_STATE_3;
15031502
break;
15041503
case NVME_POWER_STATE_STANDBY:
15051504
/* Action unspecified if POWER CONDITION MODIFIER != [0,1] */
15061505
if (pcmod == 0x0)
1507-
ps_desired = max(0, (lowest_pow_st - 2));
1506+
ps_desired = max(POWER_STATE_0, (lowest_pow_st - 2));
15081507
else if (pcmod == 0x1)
1509-
ps_desired = max(0, (lowest_pow_st - 1));
1508+
ps_desired = max(POWER_STATE_0, (lowest_pow_st - 1));
15101509
break;
15111510
case NVME_POWER_STATE_LU_CONTROL:
15121511
default:

0 commit comments

Comments
 (0)