|
@@ -1303,22 +1303,44 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
+static bool nvme_should_reset(struct nvme_dev *dev, u32 csts)
|
|
|
+{
|
|
|
+
|
|
|
+ /* If true, indicates loss of adapter communication, possibly by a
|
|
|
+ * NVMe Subsystem reset.
|
|
|
+ */
|
|
|
+ bool nssro = dev->subsystem && (csts & NVME_CSTS_NSSRO);
|
|
|
+
|
|
|
+ /* If there is a reset ongoing, we shouldn't reset again. */
|
|
|
+ if (work_busy(&dev->reset_work))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ /* We shouldn't reset unless the controller is on fatal error state
|
|
|
+ * _or_ if we lost the communication with it.
|
|
|
+ */
|
|
|
+ if (!(csts & NVME_CSTS_CFS) && !nssro)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ /* If PCI error recovery process is happening, we cannot reset or
|
|
|
+ * the recovery mechanism will surely fail.
|
|
|
+ */
|
|
|
+ if (pci_channel_offline(to_pci_dev(dev->dev)))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
static void nvme_watchdog_timer(unsigned long data)
|
|
|
{
|
|
|
struct nvme_dev *dev = (struct nvme_dev *)data;
|
|
|
u32 csts = readl(dev->bar + NVME_REG_CSTS);
|
|
|
|
|
|
- /*
|
|
|
- * Skip controllers currently under reset.
|
|
|
- */
|
|
|
- if (!work_pending(&dev->reset_work) && !work_busy(&dev->reset_work) &&
|
|
|
- ((csts & NVME_CSTS_CFS) ||
|
|
|
- (dev->subsystem && (csts & NVME_CSTS_NSSRO)))) {
|
|
|
- if (queue_work(nvme_workq, &dev->reset_work)) {
|
|
|
+ /* Skip controllers under certain specific conditions. */
|
|
|
+ if (nvme_should_reset(dev, csts)) {
|
|
|
+ if (queue_work(nvme_workq, &dev->reset_work))
|
|
|
dev_warn(dev->dev,
|
|
|
"Failed status: 0x%x, reset controller.\n",
|
|
|
csts);
|
|
|
- }
|
|
|
return;
|
|
|
}
|
|
|
|