Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci Extend the workaround for the 3ware 9650 full-qu...



details:   https://anonhg.NetBSD.org/src/rev/af89ddc2e549
branches:  trunk
changeset: 758982:af89ddc2e549
user:      dholland <dholland%NetBSD.org@localhost>
date:      Mon Nov 22 23:02:16 2010 +0000

description:
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.

diffstat:

 sys/dev/pci/twa.c    |  22 ++++++++++++++--------
 sys/dev/pci/twareg.h |   6 +++---
 sys/dev/pci/twavar.h |   6 +++++-
 3 files changed, 22 insertions(+), 12 deletions(-)

diffs (133 lines):

diff -r 808bf90d6e6a -r af89ddc2e549 sys/dev/pci/twa.c
--- a/sys/dev/pci/twa.c Mon Nov 22 22:36:54 2010 +0000
+++ b/sys/dev/pci/twa.c Mon Nov 22 23:02:16 2010 +0000
@@ -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;
diff -r 808bf90d6e6a -r af89ddc2e549 sys/dev/pci/twareg.h
--- a/sys/dev/pci/twareg.h      Mon Nov 22 22:36:54 2010 +0000
+++ b/sys/dev/pci/twareg.h      Mon Nov 22 23:02:16 2010 +0000
@@ -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));                       \
diff -r 808bf90d6e6a -r af89ddc2e549 sys/dev/pci/twavar.h
--- a/sys/dev/pci/twavar.h      Mon Nov 22 22:36:54 2010 +0000
+++ b/sys/dev/pci/twavar.h      Mon Nov 22 23:02:16 2010 +0000
@@ -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;



Home | Main Index | Thread Index | Old Index