From: Guilherme G. Piccoli Date: Tue, 14 Jun 2016 21:22:41 +0000 (-0300) Subject: nvme/quirk: Add a delay before checking for adapter readiness X-Git-Tag: release-20171130_firefly~4^2~100^2~1^2~1^2~2 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=bddc80274a128596876f8aad29afb875183c993c;p=firefly-linux-kernel-4.4.55.git nvme/quirk: Add a delay before checking for adapter readiness commit 54adc01055b75ec8769c5a36574c7a0895c0c0b2 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: Guilherme G. Piccoli Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe [mauricfo: backport to v4.4.70 without nvme quirk handling & nvme_ctrl] Signed-off-by: Mauricio Faria de Oliveira Tested-by: Narasimhan Vaidyanathan Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 044253dca30a..b8a5a8e8f57d 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -27,6 +27,13 @@ enum { 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. */ diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index c851bc53831c..e9750a0a6f2c 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -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) { + struct pci_dev *pdev = to_pci_dev(dev->dev); + dev->ctrl_config &= ~NVME_CC_SHN_MASK; dev->ctrl_config &= ~NVME_CC_ENABLE; 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); }