summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryongari <yongari@FreeBSD.org>2011-12-09 19:10:38 +0000
committeryongari <yongari@FreeBSD.org>2011-12-09 19:10:38 +0000
commit6ca8d6de98546b53f99173c5ed4de11591399483 (patch)
treef281c7113237a7ef68a7144ef8dffe307608006d
parentd172d2529b2163eb892833da9a15590946625ad4 (diff)
downloadFreeBSD-src-6ca8d6de98546b53f99173c5ed4de11591399483.zip
FreeBSD-src-6ca8d6de98546b53f99173c5ed4de11591399483.tar.gz
Announce flow control ability to PHY driver and enable RX flow
control. Controller does not automatically generate pause frames based on number of available RX buffers so it's very hard to know when driver should generate XON frame in time. The only mechanism driver can detect low number of RX buffer condition is ET_INTR_RXRING0_LOW or ET_INTR_RXRING1_LOW interrupt. This interrupt is generated whenever controller notices the number of available RX buffers are lower than pre-programmed value( ET_RX_RING0_MINCNT and ET_RX_RING1_MINCNT register). This scheme does not provide a way to detect when controller sees enough number of RX buffers again such that efficient generation of XON/XOFF frame is not easy. While here, add more flow control related register definition.
-rw-r--r--sys/dev/et/if_et.c24
-rw-r--r--sys/dev/et/if_etreg.h7
2 files changed, 27 insertions, 4 deletions
diff --git a/sys/dev/et/if_et.c b/sys/dev/et/if_et.c
index 660d35f..426ae88 100644
--- a/sys/dev/et/if_et.c
+++ b/sys/dev/et/if_et.c
@@ -332,7 +332,8 @@ et_attach(device_t dev)
et_chip_attach(sc);
error = mii_attach(dev, &sc->sc_miibus, ifp, et_ifmedia_upd,
- et_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0);
+ et_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY,
+ MIIF_DOPAUSE);
if (error) {
device_printf(dev, "attaching PHYs failed\n");
goto fail;
@@ -548,12 +549,23 @@ et_miibus_statchg(device_t dev)
if (IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) {
cfg2 |= ET_MAC_CFG2_FDX;
+ /*
+ * Controller lacks automatic TX pause frame
+ * generation so it should be handled by driver.
+ * Even though driver can send pause frame with
+ * arbitrary pause time, controller does not
+ * provide a way that tells how many free RX
+ * buffers are available in controller. This
+ * limitation makes it hard to generate XON frame
+ * in time on driver side so don't enable TX flow
+ * control.
+ */
#ifdef notyet
if (IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE)
cfg1 |= ET_MAC_CFG1_TXFLOW;
+#endif
if (IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE)
cfg1 |= ET_MAC_CFG1_RXFLOW;
-#endif
} else
ctrl |= ET_MAC_CTRL_GHDX;
@@ -1949,8 +1961,12 @@ et_init_txmac(struct et_softc *sc)
/* Disable TX MAC and FC(?) */
CSR_WRITE_4(sc, ET_TXMAC_CTRL, ET_TXMAC_CTRL_FC_DISABLE);
- /* No flow control yet */
- CSR_WRITE_4(sc, ET_TXMAC_FLOWCTRL, 0);
+ /*
+ * Initialize pause time.
+ * This register should be set before XON/XOFF frame is
+ * sent by driver.
+ */
+ CSR_WRITE_4(sc, ET_TXMAC_FLOWCTRL, 0 << ET_TXMAC_FLOWCTRL_CFPT_SHIFT);
/* Enable TX MAC but leave FC(?) diabled */
CSR_WRITE_4(sc, ET_TXMAC_CTRL,
diff --git a/sys/dev/et/if_etreg.h b/sys/dev/et/if_etreg.h
index 138bf83..a314921 100644
--- a/sys/dev/et/if_etreg.h
+++ b/sys/dev/et/if_etreg.h
@@ -193,6 +193,13 @@
#define ET_TXMAC_CTRL_FC_DISABLE 0x00000008
#define ET_TXMAC_FLOWCTRL 0x3010
+#define ET_TXMAC_FLOWCTRL_CFPT_MASK 0x0000FFFF
+#define ET_TXMAC_FLOWCTRL_CFEP_MASK 0xFFFF0000
+#define ET_TXMAC_FLOWCTRL_CFPT_SHIFT 0
+
+#define ET_TXMAC_BP_CTRL 0x3020
+#define ET_TXMAC_BP_CTRL_XONXOFF 0x00000001
+#define ET_TXMAC_BP_CTRL_REQ 0x00000002
#define ET_RXMAC_CTRL 0x4000
#define ET_RXMAC_CTRL_ENABLE 0x00000001
OpenPOWER on IntegriCloud