Module Name:    src
Committed By:   rin
Date:           Fri Nov 19 23:46:55 UTC 2021

Modified Files:
        src/sys/conf: files
        src/sys/dev/ic: ahcisata_core.c ahcisatavar.h
        src/sys/dev/pci: ahcisata_pci.c

Log Message:
ahcisata(4): Introduce AHCI_QUIRK_EXTRA_DELAY quirk for devices that
need extra delays as done by AHCISATA_EXTRA_DELAY option.

Enable this quirk for "C600/X79 AHCI". Also add commented out quirk
entries for "Bay Trail SATA (AHCI)" and "Mobile AHCI SATA Controller",
for which non-reproducible failures worked around by extra delays have
been reported.

500 ms of delays inserted by these option/quirk may be too much. Add
AHCISATA_EXTRA_DELAY_MS option to adjust number of delays in ms, like:

----
options         AHCISATA_EXTRA_DELAY_MS=200
----

Thanks prlw1@ and jun@ for testing!


To generate a diff of this commit:
cvs rdiff -u -r1.1289 -r1.1290 src/sys/conf/files
cvs rdiff -u -r1.104 -r1.105 src/sys/dev/ic/ahcisata_core.c
cvs rdiff -u -r1.26 -r1.27 src/sys/dev/ic/ahcisatavar.h
cvs rdiff -u -r1.60 -r1.61 src/sys/dev/pci/ahcisata_pci.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/conf/files
diff -u src/sys/conf/files:1.1289 src/sys/conf/files:1.1290
--- src/sys/conf/files:1.1289	Mon Oct 11 13:42:33 2021
+++ src/sys/conf/files	Fri Nov 19 23:46:54 2021
@@ -1,4 +1,4 @@
-#	$NetBSD: files,v 1.1289 2021/10/11 13:42:33 jmcneill Exp $
+#	$NetBSD: files,v 1.1290 2021/11/19 23:46:54 rin Exp $
 #	@(#)files.newconf	7.5 (Berkeley) 5/10/93
 
 version 	20171118
@@ -1036,6 +1036,7 @@ file	dev/ic/ninjaata32.c		njata
 
 # AHCI-compatible SATA controllers
 defflag	opt_ahcisata.h	AHCISATA_EXTRA_DELAY
+defparam opt_ahcisata.h	AHCISATA_EXTRA_DELAY_MS
 define ahcisata_core
 file dev/ic/ahcisata_core.c ahcisata_core
 device ahcisata: ata, ata_dma, ata_udma, sata, sata_fis, sata_pmp, ahcisata_core

Index: src/sys/dev/ic/ahcisata_core.c
diff -u src/sys/dev/ic/ahcisata_core.c:1.104 src/sys/dev/ic/ahcisata_core.c:1.105
--- src/sys/dev/ic/ahcisata_core.c:1.104	Wed Nov 10 17:19:30 2021
+++ src/sys/dev/ic/ahcisata_core.c	Fri Nov 19 23:46:55 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: ahcisata_core.c,v 1.104 2021/11/10 17:19:30 msaitoh Exp $	*/
+/*	$NetBSD: ahcisata_core.c,v 1.105 2021/11/19 23:46:55 rin Exp $	*/
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.104 2021/11/10 17:19:30 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.105 2021/11/19 23:46:55 rin Exp $");
 
 #include <sys/types.h>
 #include <sys/malloc.h>
@@ -115,6 +115,21 @@ static const struct scsipi_bustype ahci_
 #define ATA_RESET_DELAY 31000 /* 31s for a drive reset */
 #define AHCI_RST_WAIT (ATA_RESET_DELAY / 10)
 
+#ifndef AHCISATA_EXTRA_DELAY_MS
+#define	AHCISATA_EXTRA_DELAY_MS	500	/* XXX need to adjust */
+#endif
+
+#ifdef AHCISATA_EXTRA_DELAY
+#define	AHCISATA_DO_EXTRA_DELAY(sc, chp, msg, flags)			\
+    ata_delay(chp, AHCISATA_EXTRA_DELAY_MS, msg, flags)
+#else
+#define	AHCISATA_DO_EXTRA_DELAY(sc, chp, msg, flags)			\
+    do {								\
+	if ((sc)->sc_ahci_quirks & AHCI_QUIRK_EXTRA_DELAY)		\
+		ata_delay(chp, AHCISATA_EXTRA_DELAY_MS, msg, flags);	\
+    } while (0)
+#endif
+
 const struct ata_bustype ahci_ata_bustype = {
 	.bustype_type = SCSIPI_BUSTYPE_ATA,
 	.ata_bio = ahci_ata_bio,
@@ -970,9 +985,7 @@ again:
 	    AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel))), DEBUG_PROBE);
 end:
 	ahci_channel_stop(sc, chp, flags);
-#ifdef AHCISATA_EXTRA_DELAY
-	ata_delay(chp, 500, "ahcirst", flags);
-#endif
+	AHCISATA_DO_EXTRA_DELAY(sc, chp, "ahcirst", flags);
 	/* clear port interrupt register */
 	AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff);
 	ahci_channel_start(sc, chp, flags,
@@ -996,9 +1009,7 @@ ahci_reset_channel(struct ata_channel *c
 		/* XXX and then ? */
 	}
 	ata_kill_active(chp, KILL_RESET, flags);
-#ifdef AHCISATA_EXTRA_DELAY
-	ata_delay(chp, 500, "ahcirst", flags);
-#endif
+	AHCISATA_DO_EXTRA_DELAY(sc, chp, "ahcirst", flags);
 	/* clear port interrupt register */
 	AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff);
 	/* clear SErrors and start operations */
@@ -1068,9 +1079,7 @@ ahci_probe_drive(struct ata_channel *chp
 	switch (sata_reset_interface(chp, sc->sc_ahcit, achp->ahcic_scontrol,
 	    achp->ahcic_sstatus, AT_WAIT)) {
 	case SStatus_DET_DEV:
-#ifdef AHCISATA_EXTRA_DELAY
-		ata_delay(chp, 500, "ahcidv", AT_WAIT);
-#endif
+		AHCISATA_DO_EXTRA_DELAY(sc, chp, "ahcidv", AT_WAIT);
 
 		/* Initial value, used in case the soft reset fails */
 		sig = AHCI_READ(sc, AHCI_P_SIG(chp->ch_channel));
@@ -1109,10 +1118,11 @@ ahci_probe_drive(struct ata_channel *chp
 		    AHCI_P_IX_IFS |
 		    AHCI_P_IX_OFS | AHCI_P_IX_DPS | AHCI_P_IX_UFS |
 		    AHCI_P_IX_PSS | AHCI_P_IX_DHRS | AHCI_P_IX_SDBS);
-#ifdef AHCISATA_EXTRA_DELAY
-		/* wait 500ms before actually starting operations */
-		ata_delay(chp, 500, "ahciprb", AT_WAIT);
-#endif
+		/*
+		 * optionally, wait AHCISATA_EXTRA_DELAY_MS msec before
+		 * actually starting operations
+		 */
+		AHCISATA_DO_EXTRA_DELAY(sc, chp, "ahciprb", AT_WAIT);
 		break;
 
 	default:

Index: src/sys/dev/ic/ahcisatavar.h
diff -u src/sys/dev/ic/ahcisatavar.h:1.26 src/sys/dev/ic/ahcisatavar.h:1.27
--- src/sys/dev/ic/ahcisatavar.h:1.26	Mon Dec 28 14:08:42 2020
+++ src/sys/dev/ic/ahcisatavar.h	Fri Nov 19 23:46:55 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: ahcisatavar.h,v 1.26 2020/12/28 14:08:42 jmcneill Exp $	*/
+/*	$NetBSD: ahcisatavar.h,v 1.27 2021/11/19 23:46:55 rin Exp $	*/
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -59,6 +59,7 @@ struct ahci_softc {
 #define AHCI_PCI_QUIRK_BAD64	__BIT(1)  /* broken 64-bit DMA */
 #define AHCI_QUIRK_BADPMP	__BIT(2)  /* broken PMP support, ignore */
 #define AHCI_QUIRK_BADNCQ	__BIT(3)  /* possibly broken NCQ support, ignore */
+#define AHCI_QUIRK_EXTRA_DELAY	__BIT(4)  /* needs extra delay */
 
 	uint32_t sc_ahci_cap;	/* copy of AHCI_CAP */
 	int sc_ncmds; /* number of command slots */

Index: src/sys/dev/pci/ahcisata_pci.c
diff -u src/sys/dev/pci/ahcisata_pci.c:1.60 src/sys/dev/pci/ahcisata_pci.c:1.61
--- src/sys/dev/pci/ahcisata_pci.c:1.60	Fri Nov 12 07:06:06 2021
+++ src/sys/dev/pci/ahcisata_pci.c	Fri Nov 19 23:46:55 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: ahcisata_pci.c,v 1.60 2021/11/12 07:06:06 skrll Exp $	*/
+/*	$NetBSD: ahcisata_pci.c,v 1.61 2021/11/19 23:46:55 rin Exp $	*/
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ahcisata_pci.c,v 1.60 2021/11/12 07:06:06 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ahcisata_pci.c,v 1.61 2021/11/19 23:46:55 rin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ahcisata_pci.h"
@@ -204,6 +204,25 @@ static const struct ahci_pci_quirk ahci_
 	    AHCI_QUIRK_BADPMP },
 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801JI_SATA_AHCI,
 	    AHCI_QUIRK_BADPMP },
+	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C600_AHCI,
+	    AHCI_QUIRK_EXTRA_DELAY },
+#if 0
+	/*
+	 * XXX Non-reproducible failures reported. May need extra-delay quirk.
+	 */
+	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_BAYTRAIL_SATA_AHCI_0,
+	    AHCI_QUIRK_EXTRA_DELAY },
+	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_BAYTRAIL_SATA_AHCI_1,
+	    AHCI_QUIRK_EXTRA_DELAY },
+	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_SATA_4,
+	    AHCI_QUIRK_EXTRA_DELAY },
+	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_SATA_5,
+	    AHCI_QUIRK_EXTRA_DELAY },
+	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_SATA_6,
+	    AHCI_QUIRK_EXTRA_DELAY },
+	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_SATA_7,
+	    AHCI_QUIRK_EXTRA_DELAY },
+#endif
 };
 
 struct ahci_pci_softc {

Reply via email to