Commit bddc8027 authored by Guilherme G. Piccoli's avatar Guilherme G. Piccoli Committed by Greg Kroah-Hartman

nvme/quirk: Add a delay before checking for adapter readiness

commit 54adc010 upstream.

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: default avatarGuilherme G. Piccoli <gpiccoli@linux.vnet.ibm.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarJens Axboe <axboe@fb.com>
[mauricfo: backport to v4.4.70 without nvme quirk handling & nvme_ctrl]
Signed-off-by: default avatarMauricio Faria de Oliveira <mauricfo@linux.vnet.ibm.com>
Tested-by: default avatarNarasimhan Vaidyanathan <vnarasimhan@in.ibm.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent e5f87c73
...@@ -27,6 +27,13 @@ enum { ...@@ -27,6 +27,13 @@ enum {
NVME_NS_LIGHTNVM = 1, NVME_NS_LIGHTNVM = 1,
}; };
/* The below value is the specific amount of delay needed before checking
* readiness in case of the PCI_DEVICE(0x1c58, 0x0003), which needs the
* NVME_QUIRK_DELAY_BEFORE_CHK_RDY quirk enabled. The value (in ms) was
* found empirically.
*/
#define NVME_QUIRK_DELAY_AMOUNT 2000
/* /*
* Represents an NVM Express device. Each nvme_dev is a PCI function. * Represents an NVM Express device. Each nvme_dev is a PCI function.
*/ */
......
...@@ -1633,10 +1633,20 @@ static int nvme_wait_ready(struct nvme_dev *dev, u64 cap, bool enabled) ...@@ -1633,10 +1633,20 @@ static int nvme_wait_ready(struct nvme_dev *dev, u64 cap, bool enabled)
*/ */
static int nvme_disable_ctrl(struct nvme_dev *dev, u64 cap) static int nvme_disable_ctrl(struct nvme_dev *dev, u64 cap)
{ {
struct pci_dev *pdev = to_pci_dev(dev->dev);
dev->ctrl_config &= ~NVME_CC_SHN_MASK; dev->ctrl_config &= ~NVME_CC_SHN_MASK;
dev->ctrl_config &= ~NVME_CC_ENABLE; dev->ctrl_config &= ~NVME_CC_ENABLE;
writel(dev->ctrl_config, &dev->bar->cc); writel(dev->ctrl_config, &dev->bar->cc);
/* Checking for dev->tagset is a trick to avoid sleeping on module
* load, since we only need the quirk on reset_controller. Notice
* that the HGST device needs this delay only in firmware activation
* procedure; unfortunately we have no (easy) way to verify this.
*/
if (pdev->vendor == 0x1c58 && pdev->device == 0x0003 && dev->tagset)
msleep(NVME_QUIRK_DELAY_AMOUNT);
return nvme_wait_ready(dev, cap, false); return nvme_wait_ready(dev, cap, false);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment