summaryrefslogtreecommitdiff
path: root/drivers/nvme
diff options
context:
space:
mode:
authorBin Meng <bmeng.cn@gmail.com>2017-08-22 08:15:11 -0700
committerTom Rini <trini@konsulko.com>2017-08-28 07:17:12 -0400
commit04d2a3840110e495a119e6226b5c38936b48988a (patch)
tree8e7a8f85fad4e1eefde64dd0a0b62b766af269f6 /drivers/nvme
parentb65c6921433c8fcf306b4671f9f9f7c68c36cefc (diff)
nvme: Respect timeout when en/disabling the controller
So far the driver unconditionally delays 10ms when en/disabling the controller and still return 0 if 10ms times out. In fact, spec defines a timeout value in the CAP register that is the worst case time that host software shall wait for the controller to become ready. Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Diffstat (limited to 'drivers/nvme')
-rw-r--r--drivers/nvme/nvme.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
index d92273e67f..88679773a7 100644
--- a/drivers/nvme/nvme.c
+++ b/drivers/nvme/nvme.c
@@ -47,11 +47,19 @@ struct nvme_queue {
static int nvme_wait_ready(struct nvme_dev *dev, bool enabled)
{
u32 bit = enabled ? NVME_CSTS_RDY : 0;
+ int timeout;
+ ulong start;
- while ((readl(&dev->bar->csts) & NVME_CSTS_RDY) != bit)
- udelay(10000);
+ /* Timeout field in the CAP register is in 500 millisecond units */
+ timeout = NVME_CAP_TIMEOUT(dev->cap) * 500;
- return 0;
+ start = get_timer(0);
+ while (get_timer(start) < timeout) {
+ if ((readl(&dev->bar->csts) & NVME_CSTS_RDY) == bit)
+ return 0;
+ }
+
+ return -ETIME;
}
static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,