summaryrefslogtreecommitdiffstats
path: root/sys/dev/msk
diff options
context:
space:
mode:
authoryongari <yongari@FreeBSD.org>2009-05-25 07:31:18 +0000
committeryongari <yongari@FreeBSD.org>2009-05-25 07:31:18 +0000
commit4a2239202ef7d075b8bd547e4325dcce85c9a68d (patch)
treed503660db796af27afc2ce1e63d3762e16ac8e9d /sys/dev/msk
parent3be458f43d600b7c693a67db6048aedbb7ab360c (diff)
downloadFreeBSD-src-4a2239202ef7d075b8bd547e4325dcce85c9a68d.zip
FreeBSD-src-4a2239202ef7d075b8bd547e4325dcce85c9a68d.tar.gz
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 )
Diffstat (limited to 'sys/dev/msk')
-rw-r--r--sys/dev/msk/if_msk.c61
-rw-r--r--sys/dev/msk/if_mskreg.h2
2 files changed, 52 insertions, 11 deletions
diff --git a/sys/dev/msk/if_msk.c b/sys/dev/msk/if_msk.c
index 81dfa06..c3e3e4a 100644
--- a/sys/dev/msk/if_msk.c
+++ b/sys/dev/msk/if_msk.c
@@ -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, uint32_t status, int len)
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_if)
* 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)
}
}
+ 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.
diff --git a/sys/dev/msk/if_mskreg.h b/sys/dev/msk/if_mskreg.h
index c4d9030..d979419 100644
--- a/sys/dev/msk/if_mskreg.h
+++ b/sys/dev/msk/if_mskreg.h
@@ -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
OpenPOWER on IntegriCloud