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;