summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/bge/if_bge.c53
-rw-r--r--sys/dev/bge/if_bgereg.h6
2 files changed, 55 insertions, 4 deletions
diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c
index 306acc6..ee60626 100644
--- a/sys/dev/bge/if_bge.c
+++ b/sys/dev/bge/if_bge.c
@@ -2508,6 +2508,24 @@ bge_blockinit(struct bge_softc *sc)
CSR_WRITE_4(sc, BGE_RDMA_MODE, val);
DELAY(40);
+ if (sc->bge_flags & BGE_FLAG_RDMA_BUG) {
+ for (i = 0; i < BGE_NUM_RDMA_CHANNELS / 2; i++) {
+ val = CSR_READ_4(sc, BGE_RDMA_LENGTH + i * 4);
+ if ((val & 0xFFFF) > BGE_FRAMELEN)
+ break;
+ if (((val >> 16) & 0xFFFF) > BGE_FRAMELEN)
+ break;
+ }
+ if (i != BGE_NUM_RDMA_CHANNELS / 2) {
+ val = CSR_READ_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL);
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5719)
+ val |= BGE_RDMA_TX_LENGTH_WA_5719;
+ else
+ val |= BGE_RDMA_TX_LENGTH_WA_5720;
+ CSR_WRITE_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL, val);
+ }
+ }
+
/* Turn on RX data completion state machine */
CSR_WRITE_4(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE);
@@ -3319,10 +3337,18 @@ bge_attach(device_t dev)
sc->bge_flags |= BGE_FLAG_5717_PLUS | BGE_FLAG_5755_PLUS |
BGE_FLAG_575X_PLUS | BGE_FLAG_5705_PLUS | BGE_FLAG_JUMBO |
BGE_FLAG_JUMBO_FRAME;
- if (sc->bge_asicrev == BGE_ASICREV_BCM5719 &&
- sc->bge_chipid == BGE_CHIPID_BCM5719_A0) {
- /* Jumbo frame on BCM5719 A0 does not work. */
- sc->bge_flags &= ~BGE_FLAG_JUMBO;
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5719 ||
+ sc->bge_asicrev == BGE_ASICREV_BCM5720) {
+ /*
+ * Enable work around for DMA engine miscalculation
+ * of TXMBUF available space.
+ */
+ sc->bge_flags |= BGE_FLAG_RDMA_BUG;
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5719 &&
+ sc->bge_chipid == BGE_CHIPID_BCM5719_A0) {
+ /* Jumbo frame on BCM5719 A0 does not work. */
+ sc->bge_flags &= ~BGE_FLAG_JUMBO;
+ }
}
break;
case BGE_ASICREV_BCM5755:
@@ -4740,6 +4766,7 @@ bge_stats_update_regs(struct bge_softc *sc)
{
struct ifnet *ifp;
struct bge_mac_stats *stats;
+ uint32_t val;
ifp = sc->bge_ifp;
stats = &sc->bge_mac_stats;
@@ -4840,6 +4867,24 @@ bge_stats_update_regs(struct bge_softc *sc)
ifp->if_collisions = (u_long)stats->etherStatsCollisions;
ifp->if_ierrors = (u_long)(stats->NoMoreRxBDs + stats->InputDiscards +
stats->InputErrors);
+
+ if (sc->bge_flags & BGE_FLAG_RDMA_BUG) {
+ /*
+ * If controller transmitted more than BGE_NUM_RDMA_CHANNELS
+ * frames, it's safe to disable workaround for DMA engine's
+ * miscalculation of TXMBUF space.
+ */
+ if (stats->ifHCOutUcastPkts + stats->ifHCOutMulticastPkts +
+ stats->ifHCOutBroadcastPkts > BGE_NUM_RDMA_CHANNELS) {
+ val = CSR_READ_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL);
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5719)
+ val &= ~BGE_RDMA_TX_LENGTH_WA_5719;
+ else
+ val &= ~BGE_RDMA_TX_LENGTH_WA_5720;
+ CSR_WRITE_4(sc, BGE_RDMA_LSO_CRPTEN_CTRL, val);
+ sc->bge_flags &= ~BGE_FLAG_RDMA_BUG;
+ }
+ }
}
static void
diff --git a/sys/dev/bge/if_bgereg.h b/sys/dev/bge/if_bgereg.h
index 6f9822e..8ed8432 100644
--- a/sys/dev/bge/if_bgereg.h
+++ b/sys/dev/bge/if_bgereg.h
@@ -1586,6 +1586,8 @@
#define BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_512 0x00020000
#define BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_BD_4K 0x00030000
#define BGE_RDMA_LSO_CRPTEN_CTRL_BLEN_LSO_4K 0x000C0000
+#define BGE_RDMA_TX_LENGTH_WA_5719 0x02000000
+#define BGE_RDMA_TX_LENGTH_WA_5720 0x00200000
/* BD Read DMA Mode register */
#define BGE_RDMA_BD_MODE 0x4A00
@@ -1603,6 +1605,9 @@
#define BGE_RDMA_NON_LSO_MODE_RESET 0x00000001
#define BGE_RDMA_NON_LSO_MODE_ENABLE 0x00000002
+#define BGE_RDMA_LENGTH 0x4BE0
+#define BGE_NUM_RDMA_CHANNELS 4
+
/*
* Write DMA control registers
*/
@@ -2972,6 +2977,7 @@ struct bge_softc {
#define BGE_FLAG_SHORT_DMA_BUG 0x08000000
#define BGE_FLAG_4K_RDMA_BUG 0x10000000
#define BGE_FLAG_MBOX_REORDER 0x20000000
+#define BGE_FLAG_RDMA_BUG 0x40000000
uint32_t bge_mfw_flags; /* Management F/W flags */
#define BGE_MFW_ON_RXCPU 0x00000001
#define BGE_MFW_ON_APE 0x00000002
OpenPOWER on IntegriCloud