Subject: fxp i82557.c SCB timeouts in 2.0.2 on CS20 alpha
To: NetBSD/alpha Discussion List <port-alpha@netbsd.org>
From: Stephen Jones <smj@cirr.com>
List: tech-kern
Date: 06/14/2005 11:57:15
I've updated a few CS20s from 1.6.2 to 2.0.2 (the June 11th sources 
from NetBSD-2-0
release directory on the ftp site) and am seeing fairly regular SCB 
timeouts.  In 1.6.2
I had applied a patch which curbed these timeouts and I've used the 
same patch
(seen below) but haven't seen any improvement.  Does anyone have a fix?

Kernel config has:

makeoptions     COPTS="-O2 -mbwx"

The patch (which applied cleanly to the 2.0.2 source):

--- i82557.c.orig       2005-01-19 00:24:59.000000000 +0900
+++ i82557.c    2005-01-19 00:25:10.000000000 +0900
@@ -916,7 +916,7 @@
                         break;
                 m = NULL;

-               if (sc->sc_txpending == FXP_NTXCB) {
+               if (sc->sc_txpending == FXP_NTXCB - 1) {
                         FXP_EVCNT_INCR(&sc->sc_ev_txstall);
                         break;
                 }
@@ -1070,7 +1070,7 @@
  #endif
         }

-       if (sc->sc_txpending == FXP_NTXCB) {
+       if (sc->sc_txpending == FXP_NTXCB - 1) {
                 /* No more slots; notify upper layer. */
                 ifp->if_flags |= IFF_OACTIVE;
         }
@@ -1087,9 +1087,23 @@
                  * Cause the chip to interrupt and suspend command
                  * processing once the last packet we've enqueued
                  * has been transmitted.
+                *
+                * To avoid a race between updating status bits
+                * by the fxp chip and clearing command bits
+                * by this function on machines which don't have
+                * atomic methods to clear/set bits in memory
+                * smaller than 32bits (both cb_status and cb_command
+                * members are uint16_t and in the same 32bit word),
+                * we have to prepare a dummy TX descriptor which has
+                * NOP command and just causes a TX completion 
interrupt.
                  */
-               FXP_CDTX(sc, sc->sc_txlast)->txd_txcb.cb_command |=
-                   htole16(FXP_CB_COMMAND_I | FXP_CB_COMMAND_S);
+               sc->sc_txpending++;
+               sc->sc_txlast = FXP_NEXTTX(sc->sc_txlast);
+               txd = FXP_CDTX(sc, sc->sc_txlast);
+               /* BIG_ENDIAN: no need to swap to store 0 */
+               txd->txd_txcb.cb_status = 0;
+               txd->txd_txcb.cb_command = htole16(FXP_CB_COMMAND_NOP |
+                   FXP_CB_COMMAND_I | FXP_CB_COMMAND_S);
                 FXP_CDTXSYNC(sc, sc->sc_txlast,
                     BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);

@@ -1221,6 +1235,11 @@
                 FXP_CDTXSYNC(sc, i,
                     BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);

+               /* skip dummy NOP TX descriptor */
+               if ((le16toh(txd->txd_txcb.cb_command) & 
FXP_CB_COMMAND_CMD)
+                   == FXP_CB_COMMAND_NOP)
+                       continue;
+
                 txstat = le16toh(txd->txd_txcb.cb_status);

                 if ((txstat & FXP_CB_STATUS_C) == 0)
--- i82557reg.h.orig    2005-01-19 00:25:22.000000000 +0900
+++ i82557reg.h 2005-01-19 00:25:26.000000000 +0900
@@ -368,6 +368,7 @@
  #define FXP_CB_STATUS_C                0x8000

  /* commands */
+#define FXP_CB_COMMAND_CMD     0x0007  /* XXX how about FXPF_IPCB 
case? */
  #define FXP_CB_COMMAND_NOP     0x0
  #define FXP_CB_COMMAND_IAS     0x1
  #define FXP_CB_COMMAND_CONFIG  0x2