Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 26 Oct 2018 14:27:37 +0000 (UTC)
From:      Warner Losh <imp@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r339775 - head/sys/dev/nvme
Message-ID:  <201810261427.w9QERbSM085294@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: imp
Date: Fri Oct 26 14:27:37 2018
New Revision: 339775
URL: https://svnweb.freebsd.org/changeset/base/339775

Log:
  Put a workaround in for command timeout malfunctioning
  
  At least one NVMe drive has a bug that makeing the Command Time Out
  PCIe feature unreliable. The workaround is to disable this
  feature. The driver wouldn't deal correctly with a timeout anyway.
  Only do this for drives that are known bad.
  
  Sponsored by: Netflix, Inc
  Differential Revision: https://reviews.freebsd.org/D17708

Modified:
  head/sys/dev/nvme/nvme.c
  head/sys/dev/nvme/nvme_private.h

Modified: head/sys/dev/nvme/nvme.c
==============================================================================
--- head/sys/dev/nvme/nvme.c	Fri Oct 26 12:27:07 2018	(r339774)
+++ head/sys/dev/nvme/nvme.c	Fri Oct 26 14:27:37 2018	(r339775)
@@ -106,6 +106,7 @@ static struct _pcsid
 	{ 0x05401c5f,		0, 0, "Memblaze Pblaze4", QUIRK_DELAY_B4_CHK_RDY },
 	{ 0xa821144d,		0, 0, "Samsung PM1725", QUIRK_DELAY_B4_CHK_RDY },
 	{ 0xa822144d,		0, 0, "Samsung PM1725a", QUIRK_DELAY_B4_CHK_RDY },
+	{ 0x01161179,		0, 0, "Toshiba XG5", QUIRK_DISABLE_TIMEOUT },
 	{ 0x00000000,		0, 0, NULL  }
 };
 
@@ -276,6 +277,25 @@ nvme_attach(device_t dev)
 	if (status != 0) {
 		nvme_ctrlr_destruct(ctrlr, dev);
 		return (status);
+	}
+
+	/*
+	 * Some drives do not implement the completion timeout feature
+	 * correctly. There's a WAR from the manufacturer to just disable it.
+	 * The driver wouldn't respond correctly to a timeout anyway.
+	 */
+	if (ep->quirks & QUIRK_DISABLE_TIMEOUT) {
+		int ptr;
+		uint16_t devctl2;
+
+		status = pci_find_cap(dev, PCIY_EXPRESS, &ptr);
+		if (status) {
+			device_printf(dev, "Can't locate PCIe capability?");
+			return (status);
+		}
+		devctl2 = pci_read_config(dev, ptr + PCIER_DEVICE_CTL2, sizeof(devctl2));
+		devctl2 |= PCIEM_CTL2_COMP_TIMO_DISABLE;
+		pci_write_config(dev, ptr + PCIER_DEVICE_CTL2, devctl2, sizeof(devctl2));
 	}
 
 	/*

Modified: head/sys/dev/nvme/nvme_private.h
==============================================================================
--- head/sys/dev/nvme/nvme_private.h	Fri Oct 26 12:27:07 2018	(r339774)
+++ head/sys/dev/nvme/nvme_private.h	Fri Oct 26 14:27:37 2018	(r339775)
@@ -247,7 +247,8 @@ struct nvme_controller {
 
 	uint32_t		ready_timeout_in_ms;
 	uint32_t		quirks;
-#define QUIRK_DELAY_B4_CHK_RDY 1		/* Can't touch MMIO on disable */
+#define	QUIRK_DELAY_B4_CHK_RDY	1		/* Can't touch MMIO on disable */
+#define	QUIRK_DISABLE_TIMEOUT	2		/* Disable broken completion timeout feature */
 
 	bus_space_tag_t		bus_tag;
 	bus_space_handle_t	bus_handle;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201810261427.w9QERbSM085294>