diff options
author | Guilherme G. Piccoli <gpiccoli@linux.vnet.ibm.com> | 2016-06-14 17:22:41 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2016-07-12 11:23:00 -0400 |
commit | 54adc01055b75ec8769c5a36574c7a0895c0c0b2 (patch) | |
tree | 66500615cef7fe97053344365b1abe3a5e89eb38 | |
parent | 41d512e51b5e59ee2598f74249799dcc6b0a06f2 (diff) |
nvme/quirk: Add a delay before checking for adapter readiness
When disabling the controller, the specification says the register
NVME_REG_CC should be written and then driver needs to wait the
adapter to be ready, which is checked by reading another register
bit (NVME_CSTS_RDY). There's a timeout validation in this checking,
so in case this timeout is reached the driver gives up and removes
the adapter from the system.
After a firmware activation procedure, the PCI_DEVICE(0x1c58, 0x0003)
(HGST adapter) end up being removed if we issue a reset_controller,
because driver keeps verifying the NVME_REG_CSTS until the timeout is
reached. This patch adds a necessary quirk for this adapter, by
introducing a delay before nvme_wait_ready(), so the reset procedure
is able to be completed. This quirk is needed because just increasing
the timeout is not enough in case of this adapter - the driver must
wait before start reading NVME_REG_CSTS register on this specific
device.
Signed-off-by: Guilherme G. Piccoli <gpiccoli@linux.vnet.ibm.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r-- | drivers/nvme/host/core.c | 9 | ||||
-rw-r--r-- | drivers/nvme/host/nvme.h | 13 | ||||
-rw-r--r-- | drivers/nvme/host/pci.c | 2 |
3 files changed, 24 insertions, 0 deletions
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 500b790442c9..a51946a35dcf 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c | |||
@@ -1109,6 +1109,15 @@ int nvme_disable_ctrl(struct nvme_ctrl *ctrl, u64 cap) | |||
1109 | ret = ctrl->ops->reg_write32(ctrl, NVME_REG_CC, ctrl->ctrl_config); | 1109 | ret = ctrl->ops->reg_write32(ctrl, NVME_REG_CC, ctrl->ctrl_config); |
1110 | if (ret) | 1110 | if (ret) |
1111 | return ret; | 1111 | return ret; |
1112 | |||
1113 | /* Checking for ctrl->tagset is a trick to avoid sleeping on module | ||
1114 | * load, since we only need the quirk on reset_controller. Notice | ||
1115 | * that the HGST device needs this delay only in firmware activation | ||
1116 | * procedure; unfortunately we have no (easy) way to verify this. | ||
1117 | */ | ||
1118 | if ((ctrl->quirks & NVME_QUIRK_DELAY_BEFORE_CHK_RDY) && ctrl->tagset) | ||
1119 | msleep(NVME_QUIRK_DELAY_AMOUNT); | ||
1120 | |||
1112 | return nvme_wait_ready(ctrl, cap, false); | 1121 | return nvme_wait_ready(ctrl, cap, false); |
1113 | } | 1122 | } |
1114 | EXPORT_SYMBOL_GPL(nvme_disable_ctrl); | 1123 | EXPORT_SYMBOL_GPL(nvme_disable_ctrl); |
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index abe83b43a71a..1bd42d5f9e0e 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h | |||
@@ -68,8 +68,21 @@ enum nvme_quirks { | |||
68 | * logical blocks. | 68 | * logical blocks. |
69 | */ | 69 | */ |
70 | NVME_QUIRK_DISCARD_ZEROES = (1 << 2), | 70 | NVME_QUIRK_DISCARD_ZEROES = (1 << 2), |
71 | |||
72 | /* | ||
73 | * The controller needs a delay before starts checking the device | ||
74 | * readiness, which is done by reading the NVME_CSTS_RDY bit. | ||
75 | */ | ||
76 | NVME_QUIRK_DELAY_BEFORE_CHK_RDY = (1 << 3), | ||
71 | }; | 77 | }; |
72 | 78 | ||
79 | /* The below value is the specific amount of delay needed before checking | ||
80 | * readiness in case of the PCI_DEVICE(0x1c58, 0x0003), which needs the | ||
81 | * NVME_QUIRK_DELAY_BEFORE_CHK_RDY quirk enabled. The value (in ms) was | ||
82 | * found empirically. | ||
83 | */ | ||
84 | #define NVME_QUIRK_DELAY_AMOUNT 2000 | ||
85 | |||
73 | enum nvme_ctrl_state { | 86 | enum nvme_ctrl_state { |
74 | NVME_CTRL_NEW, | 87 | NVME_CTRL_NEW, |
75 | NVME_CTRL_LIVE, | 88 | NVME_CTRL_LIVE, |
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 79a4f56c06cd..846a42977068 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c | |||
@@ -2094,6 +2094,8 @@ static const struct pci_device_id nvme_id_table[] = { | |||
2094 | NVME_QUIRK_DISCARD_ZEROES, }, | 2094 | NVME_QUIRK_DISCARD_ZEROES, }, |
2095 | { PCI_VDEVICE(INTEL, 0x5845), /* Qemu emulated controller */ | 2095 | { PCI_VDEVICE(INTEL, 0x5845), /* Qemu emulated controller */ |
2096 | .driver_data = NVME_QUIRK_IDENTIFY_CNS, }, | 2096 | .driver_data = NVME_QUIRK_IDENTIFY_CNS, }, |
2097 | { PCI_DEVICE(0x1c58, 0x0003), /* HGST adapter */ | ||
2098 | .driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, }, | ||
2097 | { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) }, | 2099 | { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) }, |
2098 | { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001) }, | 2100 | { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001) }, |
2099 | { 0, } | 2101 | { 0, } |