summaryrefslogtreecommitdiffstats
path: root/drivers/nvme
diff options
context:
space:
mode:
authorNiklas Cassel <niklas.cassel@wdc.com>2022-05-26 15:57:21 +0200
committerChristoph Hellwig <hch@lst.de>2022-05-31 07:41:22 +0200
commitaa41d2fe60ee2e4452b0f9ca9f0f6d80a4ff9f9d (patch)
treeb5d273303a567486054e9c5dcdfd8a94c134cc79 /drivers/nvme
parent70ce3455345d056b5fc427c3bb4a3ff4d126b6d5 (diff)
downloadlinux-stable-aa41d2fe60ee2e4452b0f9ca9f0f6d80a4ff9f9d.tar.gz
linux-stable-aa41d2fe60ee2e4452b0f9ca9f0f6d80a4ff9f9d.tar.bz2
linux-stable-aa41d2fe60ee2e4452b0f9ca9f0f6d80a4ff9f9d.zip
nvme: set controller enable bit in a separate write
The NVM Express Base Specification 2.0 specifies in the description of the CC – Controller Configuration register: "Host software shall set the Arbitration Mechanism Selected (CC.AMS), the Memory Page Size (CC.MPS), and the I/O Command Set Selected (CC.CSS) to valid values prior to enabling the controller by setting CC.EN to ‘1’. While we haven't seen any controller misbehaving while setting all bits in a single write, let's do it in the order that it is written in the spec, as there could potentially be controllers that are implemented to rely on the configuration bits being set before enabling the controller. Signed-off-by: Niklas Cassel <niklas.cassel@wdc.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'drivers/nvme')
-rw-r--r--drivers/nvme/host/core.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index a7660e4be55b..98e343cb4a12 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -2227,8 +2227,16 @@ int nvme_enable_ctrl(struct nvme_ctrl *ctrl)
ctrl->ctrl_config |= (NVME_CTRL_PAGE_SHIFT - 12) << NVME_CC_MPS_SHIFT;
ctrl->ctrl_config |= NVME_CC_AMS_RR | NVME_CC_SHN_NONE;
ctrl->ctrl_config |= NVME_CC_IOSQES | NVME_CC_IOCQES;
- ctrl->ctrl_config |= NVME_CC_ENABLE;
+ ret = ctrl->ops->reg_write32(ctrl, NVME_REG_CC, ctrl->ctrl_config);
+ if (ret)
+ return ret;
+ /* Flush write to device (required if transport is PCI) */
+ ret = ctrl->ops->reg_read32(ctrl, NVME_REG_CC, &ctrl->ctrl_config);
+ if (ret)
+ return ret;
+
+ ctrl->ctrl_config |= NVME_CC_ENABLE;
ret = ctrl->ops->reg_write32(ctrl, NVME_REG_CC, ctrl->ctrl_config);
if (ret)
return ret;