Module Name:    src
Committed By:   dholland
Date:           Mon Nov 22 23:02:16 UTC 2010

Modified Files:
        src/sys/dev/pci: twa.c twareg.h twavar.h

Log Message:
Extend the workaround for the 3ware 9650 full-queue bug to a full-fledged
quirk, and use it for the 9690 as well where it's also needed. Patch by me,
problem hunted down by Jiri Novotny and Zdenek Slavet and reported in
PR 44002.


To generate a diff of this commit:
cvs rdiff -u -r1.35 -r1.36 src/sys/dev/pci/twa.c
cvs rdiff -u -r1.10 -r1.11 src/sys/dev/pci/twareg.h
cvs rdiff -u -r1.9 -r1.10 src/sys/dev/pci/twavar.h

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

Modified files:

Index: src/sys/dev/pci/twa.c
diff -u src/sys/dev/pci/twa.c:1.35 src/sys/dev/pci/twa.c:1.36
--- src/sys/dev/pci/twa.c:1.35	Sun Nov 14 05:33:44 2010
+++ src/sys/dev/pci/twa.c	Mon Nov 22 23:02:16 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: twa.c,v 1.35 2010/11/14 05:33:44 uebayasi Exp $ */
+/*	$NetBSD: twa.c,v 1.36 2010/11/22 23:02:16 dholland Exp $ */
 /*	$wasabi: twa.c,v 1.27 2006/07/28 18:17:21 wrstuden Exp $	*/
 
 /*-
@@ -67,7 +67,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: twa.c,v 1.35 2010/11/14 05:33:44 uebayasi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: twa.c,v 1.36 2010/11/22 23:02:16 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1054,16 +1054,18 @@
 	s = splbio();
 
 	/*
-	 * The 9650 has a bug in the detection of the full queue condition.
+	 * The 9650 and 9690 have a bug in the detection of the full queue
+	 * condition.
+	 *
 	 * If a write operation has filled the queue and is directly followed
 	 * by a status read, it sometimes doesn't return the correct result.
 	 * To work around this, the upper 32bit are written first.
 	 * This effectively serialises the hardware, but does not change
 	 * the state of the queue.
 	 */
-	if (sc->sc_product_id == PCI_PRODUCT_3WARE_9650) {
+	if (sc->sc_quirks & TWA_QUIRK_QUEUEFULL_BUG) {
 		/* Write lower 32 bits of address */
-		TWA_WRITE_9650_COMMAND_QUEUE_LOW(sc, tr->tr_cmd_phys +
+		TWA_WRITE_COMMAND_QUEUE_LOW(sc, tr->tr_cmd_phys +
 			sizeof(struct twa_command_header));
 	}
 
@@ -1087,12 +1089,12 @@
 			sizeof(struct twa_command_packet),
 			BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
-		if (sc->sc_product_id == PCI_PRODUCT_3WARE_9650) {
+		if (sc->sc_quirks & TWA_QUIRK_QUEUEFULL_BUG) {
 			/*
-			 * Cmd queue is not full.  Post the command to 9650
+			 * Cmd queue is not full.  Post the command
 			 * by writing upper 32 bits of address.
 			 */
-			TWA_WRITE_9650_COMMAND_QUEUE_HIGH(sc, tr->tr_cmd_phys +
+			TWA_WRITE_COMMAND_QUEUE_HIGH(sc, tr->tr_cmd_phys +
 				sizeof(struct twa_command_header));
 		} else {
 			/* Cmd queue is not full.  Post the command. */
@@ -1505,6 +1507,8 @@
 
 	aprint_naive(": RAID controller\n");
 	aprint_normal(": 3ware Apache\n");
+
+	sc->sc_quirks = 0;
 		
 	if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_3WARE_9000) {
 		sc->sc_nunits = TWA_MAX_UNITS;
@@ -1532,6 +1536,7 @@
 			aprint_error_dev(&sc->twa_dv, "can't map mem space\n");
 			return;
 		}
+		sc->sc_quirks |= TWA_QUIRK_QUEUEFULL_BUG;
 	} else if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_3WARE_9690) {
 		sc->sc_nunits = TWA_9690_MAX_UNITS;
 		use_64bit = true;
@@ -1541,6 +1546,7 @@
 			aprint_error_dev(&sc->twa_dv, "can't map mem space\n");
 			return;
 		}
+		sc->sc_quirks |= TWA_QUIRK_QUEUEFULL_BUG;
 	} else {
 		sc->sc_nunits = 0;
 		use_64bit = false;

Index: src/sys/dev/pci/twareg.h
diff -u src/sys/dev/pci/twareg.h:1.10 src/sys/dev/pci/twareg.h:1.11
--- src/sys/dev/pci/twareg.h:1.10	Mon Sep  8 23:36:54 2008
+++ src/sys/dev/pci/twareg.h	Mon Nov 22 23:02:16 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: twareg.h,v 1.10 2008/09/08 23:36:54 gmcgarry Exp $ */
+/*	$NetBSD: twareg.h,v 1.11 2010/11/22 23:02:16 dholland Exp $ */
 /*	$wasabi: twareg.h,v 1.14 2006/07/28 18:29:51 wrstuden Exp $ */
 
 /*-
@@ -102,13 +102,13 @@
 	} while (0)
 #endif
 
-#define TWA_WRITE_9650_COMMAND_QUEUE_HIGH(sc, val)			\
+#define TWA_WRITE_COMMAND_QUEUE_HIGH(sc, val)				\
 	do {								\
 		TWA_WRITE_REGISTER(sc, TWA_COMMAND_QUEUE_OFFSET_HIGH,	\
 				(uint32_t)(((uint64_t)val)>>32));	\
 	} while (0)
 
-#define TWA_WRITE_9650_COMMAND_QUEUE_LOW(sc, val)			\
+#define TWA_WRITE_COMMAND_QUEUE_LOW(sc, val)				\
 	do {								\
 		TWA_WRITE_REGISTER(sc, TWA_COMMAND_QUEUE_OFFSET_LOW,	\
 				(uint32_t)(val));			\

Index: src/sys/dev/pci/twavar.h
diff -u src/sys/dev/pci/twavar.h:1.9 src/sys/dev/pci/twavar.h:1.10
--- src/sys/dev/pci/twavar.h:1.9	Wed May  6 10:34:33 2009
+++ src/sys/dev/pci/twavar.h	Mon Nov 22 23:02:16 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: twavar.h,v 1.9 2009/05/06 10:34:33 cegger Exp $ */
+/*	$NetBSD: twavar.h,v 1.10 2010/11/22 23:02:16 dholland Exp $ */
 /*	$wasabi: twavar.h,v 1.12 2006/05/01 15:16:59 simonb Exp $	*/
 
 /*-
@@ -107,6 +107,7 @@
 
 	struct twa_request      *sc_twa_request;
 	uint32_t		sc_product_id;
+	unsigned		sc_quirks;
 };
 
 
@@ -145,6 +146,9 @@
 #define TWA_LOCK_FREE		0x0	/* lock is free */
 #define TWA_LOCK_HELD		0x1	/* lock is held */
 
+/* Possible values of sc->sc_quirks. */
+#define TWA_QUIRK_QUEUEFULL_BUG	0x1
+
 /* Driver's request packet. */
 struct twa_request {
 	struct twa_command_packet *tr_command;

Reply via email to