Announce flow control capability to PHY drivers and enable flow
control for all vr(4) controllers that support it. It's known that old vr(4) controllers(Rhine II) does not support TX pause but Rhine III supports both TX and RX pause. Make TX pause really work on Rhine III by letting controller know available RX buffers. While here, adjust XON/XOFF parameters to get better performance with flow control.
This commit is contained in:
parent
95671c0c24
commit
11947ff83f
@ -305,7 +305,7 @@ vr_miibus_statchg(device_t dev)
|
|||||||
(ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
|
(ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sc->vr_flags &= ~VR_F_LINK;
|
sc->vr_flags &= ~(VR_F_LINK | VR_F_TXPAUSE);
|
||||||
if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
|
if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
|
||||||
(IFM_ACTIVE | IFM_AVALID)) {
|
(IFM_ACTIVE | IFM_AVALID)) {
|
||||||
switch (IFM_SUBTYPE(mii->mii_media_active)) {
|
switch (IFM_SUBTYPE(mii->mii_media_active)) {
|
||||||
@ -342,7 +342,6 @@ vr_miibus_statchg(device_t dev)
|
|||||||
CSR_WRITE_1(sc, VR_CR1, cr1);
|
CSR_WRITE_1(sc, VR_CR1, cr1);
|
||||||
}
|
}
|
||||||
fc = 0;
|
fc = 0;
|
||||||
#ifdef notyet
|
|
||||||
/* Configure flow-control. */
|
/* Configure flow-control. */
|
||||||
if (sc->vr_revid >= REV_ID_VT6105_A0) {
|
if (sc->vr_revid >= REV_ID_VT6105_A0) {
|
||||||
fc = CSR_READ_1(sc, VR_FLOWCR1);
|
fc = CSR_READ_1(sc, VR_FLOWCR1);
|
||||||
@ -351,8 +350,10 @@ vr_miibus_statchg(device_t dev)
|
|||||||
IFM_ETH_RXPAUSE) != 0)
|
IFM_ETH_RXPAUSE) != 0)
|
||||||
fc |= VR_FLOWCR1_RXPAUSE;
|
fc |= VR_FLOWCR1_RXPAUSE;
|
||||||
if ((IFM_OPTIONS(mii->mii_media_active) &
|
if ((IFM_OPTIONS(mii->mii_media_active) &
|
||||||
IFM_ETH_TXPAUSE) != 0)
|
IFM_ETH_TXPAUSE) != 0) {
|
||||||
fc |= VR_FLOWCR1_TXPAUSE;
|
fc |= VR_FLOWCR1_TXPAUSE;
|
||||||
|
sc->vr_flags |= VR_F_TXPAUSE;
|
||||||
|
}
|
||||||
CSR_WRITE_1(sc, VR_FLOWCR1, fc);
|
CSR_WRITE_1(sc, VR_FLOWCR1, fc);
|
||||||
} else if (sc->vr_revid >= REV_ID_VT6102_A) {
|
} else if (sc->vr_revid >= REV_ID_VT6102_A) {
|
||||||
/* No Tx puase capability available for Rhine II. */
|
/* No Tx puase capability available for Rhine II. */
|
||||||
@ -363,7 +364,6 @@ vr_miibus_statchg(device_t dev)
|
|||||||
fc |= VR_MISCCR0_RXPAUSE;
|
fc |= VR_MISCCR0_RXPAUSE;
|
||||||
CSR_WRITE_1(sc, VR_MISC_CR0, fc);
|
CSR_WRITE_1(sc, VR_MISC_CR0, fc);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
vr_rx_start(sc);
|
vr_rx_start(sc);
|
||||||
vr_tx_start(sc);
|
vr_tx_start(sc);
|
||||||
} else {
|
} else {
|
||||||
@ -766,7 +766,8 @@ vr_attach(device_t dev)
|
|||||||
else
|
else
|
||||||
phy = CSR_READ_1(sc, VR_PHYADDR) & VR_PHYADDR_MASK;
|
phy = CSR_READ_1(sc, VR_PHYADDR) & VR_PHYADDR_MASK;
|
||||||
error = mii_attach(dev, &sc->vr_miibus, ifp, vr_ifmedia_upd,
|
error = mii_attach(dev, &sc->vr_miibus, ifp, vr_ifmedia_upd,
|
||||||
vr_ifmedia_sts, BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0);
|
vr_ifmedia_sts, BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY,
|
||||||
|
sc->vr_revid >= REV_ID_VT6102_A ? MIIF_DOPAUSE : 0);
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
device_printf(dev, "attaching PHYs failed\n");
|
device_printf(dev, "attaching PHYs failed\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -1396,6 +1397,17 @@ vr_rxeof(struct vr_softc *sc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (prog > 0) {
|
if (prog > 0) {
|
||||||
|
/*
|
||||||
|
* Let controller know how many number of RX buffers
|
||||||
|
* are posted but avoid expensive register access if
|
||||||
|
* TX pause capability was not negotiated with link
|
||||||
|
* partner.
|
||||||
|
*/
|
||||||
|
if ((sc->vr_flags & VR_F_TXPAUSE) != 0) {
|
||||||
|
if (prog >= VR_RX_RING_CNT)
|
||||||
|
prog = VR_RX_RING_CNT - 1;
|
||||||
|
CSR_WRITE_1(sc, VR_FLOWCR0, prog);
|
||||||
|
}
|
||||||
sc->vr_cdata.vr_rx_cons = cons;
|
sc->vr_cdata.vr_rx_cons = cons;
|
||||||
bus_dmamap_sync(sc->vr_cdata.vr_rx_ring_tag,
|
bus_dmamap_sync(sc->vr_cdata.vr_rx_ring_tag,
|
||||||
sc->vr_cdata.vr_rx_ring_map,
|
sc->vr_cdata.vr_rx_ring_map,
|
||||||
@ -2071,14 +2083,32 @@ vr_init_locked(struct vr_softc *sc)
|
|||||||
|
|
||||||
/* Set flow-control parameters for Rhine III. */
|
/* Set flow-control parameters for Rhine III. */
|
||||||
if (sc->vr_revid >= REV_ID_VT6105_A0) {
|
if (sc->vr_revid >= REV_ID_VT6105_A0) {
|
||||||
/* Rx buffer count available for incoming packet. */
|
|
||||||
CSR_WRITE_1(sc, VR_FLOWCR0, VR_RX_RING_CNT);
|
|
||||||
/*
|
/*
|
||||||
* Tx pause low threshold : 16 free receive buffers
|
* Configure Rx buffer count available for incoming
|
||||||
* Tx pause XON high threshold : 48 free receive buffers
|
* packet.
|
||||||
|
* Even though data sheet says almost nothing about
|
||||||
|
* this register, this register should be updated
|
||||||
|
* whenever driver adds new RX buffers to controller.
|
||||||
|
* Otherwise, XON frame is not sent to link partner
|
||||||
|
* even if controller has enough RX buffers and you
|
||||||
|
* would be isolated from network.
|
||||||
|
* The controller is not smart enough to know number
|
||||||
|
* of available RX buffers so driver have to let
|
||||||
|
* controller know how many RX buffers are posted.
|
||||||
|
* In other words, this register works like a residue
|
||||||
|
* counter for RX buffers and should be initialized
|
||||||
|
* to the number of total RX buffers - 1 before
|
||||||
|
* enabling RX MAC. Note, this register is 8bits so
|
||||||
|
* it effectively limits the maximum number of RX
|
||||||
|
* buffer to be configured by controller is 255.
|
||||||
|
*/
|
||||||
|
CSR_WRITE_1(sc, VR_FLOWCR0, VR_RX_RING_CNT - 1);
|
||||||
|
/*
|
||||||
|
* Tx pause low threshold : 8 free receive buffers
|
||||||
|
* Tx pause XON high threshold : 24 free receive buffers
|
||||||
*/
|
*/
|
||||||
CSR_WRITE_1(sc, VR_FLOWCR1,
|
CSR_WRITE_1(sc, VR_FLOWCR1,
|
||||||
VR_FLOWCR1_TXLO16 | VR_FLOWCR1_TXHI48 | VR_FLOWCR1_XONXOFF);
|
VR_FLOWCR1_TXLO8 | VR_FLOWCR1_TXHI24 | VR_FLOWCR1_XONXOFF);
|
||||||
/* Set Tx pause timer. */
|
/* Set Tx pause timer. */
|
||||||
CSR_WRITE_2(sc, VR_PAUSETIMER, 0xffff);
|
CSR_WRITE_2(sc, VR_PAUSETIMER, 0xffff);
|
||||||
}
|
}
|
||||||
@ -2106,7 +2136,7 @@ vr_init_locked(struct vr_softc *sc)
|
|||||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||||
|
|
||||||
sc->vr_flags &= ~VR_F_LINK;
|
sc->vr_flags &= ~(VR_F_LINK | VR_F_TXPAUSE);
|
||||||
mii_mediachg(mii);
|
mii_mediachg(mii);
|
||||||
|
|
||||||
callout_reset(&sc->vr_stat_callout, hz, vr_tick, sc);
|
callout_reset(&sc->vr_stat_callout, hz, vr_tick, sc);
|
||||||
@ -2128,6 +2158,7 @@ vr_ifmedia_upd(struct ifnet *ifp)
|
|||||||
mii = device_get_softc(sc->vr_miibus);
|
mii = device_get_softc(sc->vr_miibus);
|
||||||
LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
|
LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
|
||||||
PHY_RESET(miisc);
|
PHY_RESET(miisc);
|
||||||
|
sc->vr_flags &= ~(VR_F_LINK | VR_F_TXPAUSE);
|
||||||
error = mii_mediachg(mii);
|
error = mii_mediachg(mii);
|
||||||
VR_UNLOCK(sc);
|
VR_UNLOCK(sc);
|
||||||
|
|
||||||
|
@ -722,6 +722,7 @@ struct vr_softc {
|
|||||||
uint8_t vr_revid; /* Rhine chip revision */
|
uint8_t vr_revid; /* Rhine chip revision */
|
||||||
int vr_flags; /* See VR_F_* below */
|
int vr_flags; /* See VR_F_* below */
|
||||||
#define VR_F_RESTART 0x0001 /* Restart unit on next tick */
|
#define VR_F_RESTART 0x0001 /* Restart unit on next tick */
|
||||||
|
#define VR_F_TXPAUSE 0x0010
|
||||||
#define VR_F_SUSPENDED 0x2000
|
#define VR_F_SUSPENDED 0x2000
|
||||||
#define VR_F_DETACHED 0x4000
|
#define VR_F_DETACHED 0x4000
|
||||||
#define VR_F_LINK 0x8000
|
#define VR_F_LINK 0x8000
|
||||||
|
Loading…
Reference in New Issue
Block a user