Author: yongari
Date: Mon May 25 07:31:18 2009
New Revision: 192735
URL: http://svn.freebsd.org/changeset/base/192735

Log:
  Add workaround for Yukon FE+ A0. This controller is known to have
  severe silicon bugs that can't handle VLAN hardware tagging as well
  as status LE writeback bug. The status LE writeback bug is so
  critical we can't trust status word of received frame. To accept
  frames on Yukon FE+ A0 msk(4) just do minimal check for received
  frames and pass them to upper stack. This means msk(4) can pass
  corrupted frames to upper layer. You have been warned!
  Also I supposed RX_GMF_FL_THR to be 32bits register but Linux
  driver treated it as 16bit register so follow their leads. At least
  this does not seem to break msk(4) on Yukon FE+.
  
  Tested by:    bz, Tanguy Bouzeloc ( the.zauron <> gmail dot com )
                Bruce Cran ( bruce <> cran dot org dot uk )
                Michael Reifenberger ( mike <> reifenberger dot com )
                Stephen Montgomery-Smith ( stephen <> missouri dot edu )

Modified:
  head/sys/dev/msk/if_msk.c
  head/sys/dev/msk/if_mskreg.h

Modified: head/sys/dev/msk/if_msk.c
==============================================================================
--- head/sys/dev/msk/if_msk.c   Mon May 25 07:06:10 2009        (r192734)
+++ head/sys/dev/msk/if_msk.c   Mon May 25 07:31:18 2009        (r192735)
@@ -1493,14 +1493,17 @@ msk_attach(device_t dev)
        ether_ifattach(ifp, eaddr);
        MSK_IF_LOCK(sc_if);
 
-       /*
-        * VLAN capability setup 
-        * Due to Tx checksum offload hardware bugs, msk(4) manually
-        * computes checksum for short frames. For VLAN tagged frames
-        * this workaround does not work so disable checksum offload
-        * for VLAN interface.
-        */
-       ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING;
+       /* VLAN capability setup */
+       ifp->if_capabilities |= IFCAP_VLAN_MTU;
+       if ((sc_if->msk_flags & MSK_FLAG_NOHWVLAN) == 0) {
+               /*
+                * Due to Tx checksum offload hardware bugs, msk(4) manually
+                * computes checksum for short frames. For VLAN tagged frames
+                * this workaround does not work so disable checksum offload
+                * for VLAN interface.
+                */
+               ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
+       }
        ifp->if_capenable = ifp->if_capabilities;
 
        /*
@@ -1646,6 +1649,19 @@ mskc_attach(device_t dev)
        case CHIP_ID_YUKON_FE_P:
                sc->msk_clock = 50;     /* 50 Mhz */
                sc->msk_pflags |= MSK_FLAG_FASTETHER | MSK_FLAG_DESCV2;
+               if (sc->msk_hw_rev == CHIP_REV_YU_FE_P_A0) {
+                       /*
+                        * XXX
+                        * FE+ A0 has status LE writeback bug so msk(4)
+                        * does not rely on status word of received frame
+                        * in msk_rxeof() which in turn disables all
+                        * hardware assistance bits reported by the status
+                        * word as well as validity of the recevied frame.
+                        * Just pass received frames to upper stack with
+                        * minimal test and let upper stack handle them.
+                        */
+                       sc->msk_pflags |= MSK_FLAG_NOHWVLAN | MSK_FLAG_NORXCHK;
+               }
                break;
        case CHIP_ID_YUKON_XL:
                sc->msk_clock = 156;    /* 156 Mhz */
@@ -2882,7 +2898,18 @@ msk_rxeof(struct msk_if_softc *sc_if, ui
                if ((status & GMR_FS_VLAN) != 0 &&
                    (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0)
                        rxlen -= ETHER_VLAN_ENCAP_LEN;
-               if (len > sc_if->msk_framesize ||
+               if ((sc_if->msk_flags & MSK_FLAG_NORXCHK) != 0) {
+                       /*
+                        * For controllers that returns bogus status code
+                        * just do minimal check and let upper stack
+                        * handle this frame.
+                        */
+                       if (len > MSK_MAX_FRAMELEN || len < ETHER_HDR_LEN) {
+                               ifp->if_ierrors++;
+                               msk_discard_rxbuf(sc_if, cons);
+                               break;
+                       }
+               } else if (len > sc_if->msk_framesize ||
                    ((status & GMR_FS_ANY_ERR) != 0) ||
                    ((status & GMR_FS_RX_OK) == 0) || (rxlen != len)) {
                        /* Don't count flow-control packet as errors. */
@@ -3613,8 +3640,12 @@ msk_init_locked(struct msk_if_softc *sc_
         * Set Rx FIFO flush threshold to 64 bytes + 1 FIFO word
         * due to hardware hang on receipt of pause frames.
         */
-       CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_FL_THR),
-           RX_GMF_FL_THR_DEF + 1);
+       reg = RX_GMF_FL_THR_DEF + 1;
+       /* Another magic for Yukon FE+ - From Linux. */
+       if (sc->msk_hw_id == CHIP_ID_YUKON_FE_P &&
+           sc->msk_hw_rev == CHIP_REV_YU_FE_P_A0)
+               reg = 0x178;
+       CSR_WRITE_2(sc, MR_ADDR(sc_if->msk_port, RX_GMF_FL_THR), reg);
 
        /* Configure Tx MAC FIFO. */
        CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), GMF_RST_SET);
@@ -3646,6 +3677,14 @@ msk_init_locked(struct msk_if_softc *sc_
                }
        }
 
+       if (sc->msk_hw_id == CHIP_ID_YUKON_FE_P &&
+           sc->msk_hw_rev == CHIP_REV_YU_FE_P_A0) {
+               /* Disable dynamic watermark - from Linux. */
+               reg = CSR_READ_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_EA));
+               reg &= ~0x03;
+               CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_EA), reg);
+       }
+
        /*
         * Disable Force Sync bit and Alloc bit in Tx RAM interface
         * arbiter as we don't use Sync Tx queue.

Modified: head/sys/dev/msk/if_mskreg.h
==============================================================================
--- head/sys/dev/msk/if_mskreg.h        Mon May 25 07:06:10 2009        
(r192734)
+++ head/sys/dev/msk/if_mskreg.h        Mon May 25 07:31:18 2009        
(r192735)
@@ -2396,6 +2396,8 @@ struct msk_if_softc {
 #define        MSK_FLAG_JUMBO_NOCSUM   0x0010
 #define        MSK_FLAG_RAMBUF         0x0020
 #define        MSK_FLAG_DESCV2         0x0040
+#define        MSK_FLAG_NOHWVLAN       0x0080
+#define        MSK_FLAG_NORXCHK        0x0100
 #define        MSK_FLAG_SUSPEND        0x2000
 #define        MSK_FLAG_DETACH         0x4000
 #define        MSK_FLAG_LINK           0x8000
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to