Skip to content

Commit f0377ff

Browse files
maurizio-lombardikeithbusch
authored andcommitted
nvme-host: fix the updating of the firmware version
The original code didn't update the firmware version if the "next slot" of the AFI register isn't zero or if the "current slot" field is zero; in those cases it assumed that a reset was needed. However, the NVMe specification doesn't exclude the possibility that the "next slot" value is equal to the "current slot" value, meaning that the same firmware slot will be activated after performing a controller level reset; in this case a reset is clearly not necessary and we can safely update the firmware version. Modify the code so the kernel will report that a Controller Level Reset is needed only in the following cases: 1) If the "current slot" field is zero. This is invalid and means that something is wrong, a reset is needed. or 2) if the "next slot" field isn't zero AND it's not equal to the "current slot" value. This means that at the next reset a different firmware slot will be activated. Fixes: 983a338 ("nvme: update firmware version after commit") Signed-off-by: Maurizio Lombardi <mlombard@redhat.com> Reviewed-by: Daniel Wagner <dwagner@suse.de> Signed-off-by: Keith Busch <kbusch@kernel.org>
1 parent 3735816 commit f0377ff

File tree

1 file changed

+5
-2
lines changed

1 file changed

+5
-2
lines changed

drivers/nvme/host/core.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4191,6 +4191,7 @@ static bool nvme_ctrl_pp_status(struct nvme_ctrl *ctrl)
41914191
static void nvme_get_fw_slot_info(struct nvme_ctrl *ctrl)
41924192
{
41934193
struct nvme_fw_slot_info_log *log;
4194+
u8 next_fw_slot, cur_fw_slot;
41944195

41954196
log = kmalloc(sizeof(*log), GFP_KERNEL);
41964197
if (!log)
@@ -4202,13 +4203,15 @@ static void nvme_get_fw_slot_info(struct nvme_ctrl *ctrl)
42024203
goto out_free_log;
42034204
}
42044205

4205-
if (log->afi & 0x70 || !(log->afi & 0x7)) {
4206+
cur_fw_slot = log->afi & 0x7;
4207+
next_fw_slot = (log->afi & 0x70) >> 4;
4208+
if (!cur_fw_slot || (next_fw_slot && (cur_fw_slot != next_fw_slot))) {
42064209
dev_info(ctrl->device,
42074210
"Firmware is activated after next Controller Level Reset\n");
42084211
goto out_free_log;
42094212
}
42104213

4211-
memcpy(ctrl->subsys->firmware_rev, &log->frs[(log->afi & 0x7) - 1],
4214+
memcpy(ctrl->subsys->firmware_rev, &log->frs[cur_fw_slot - 1],
42124215
sizeof(ctrl->subsys->firmware_rev));
42134216

42144217
out_free_log:

0 commit comments

Comments
 (0)