From 6d2b26f4a09474eec399b2bb9e5e0e5e3eb37e13 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 8 Feb 2007 19:16:15 +0000 Subject: [PATCH] Fix problem with RTL8201L PHY. From submitter: Bugfix for the Realtek PHY driver... an RTL8201L standalone PHY needs different handling than the integrated ones in terms of speed detection. There was a bogus test based on the parent device driver name string controlling which speed register to query. That test began failing when the rl driver was split into separate rl and re drivers some time ago. Apparently nobody ever noticed because the buggy code only executes if NWAY negotiation failed. Since we happen to be testing with an ancient dumb hub rather than a modern switch, we found it. To fix it all, have the attach() routine notice whether we're dealing with an integrated PHY or an RTL8201L and store that info in a struct accessible to the status() routine that needs to know which register to query. I touched up the fixes because they were relative to RELENG_6 and to bring a few nits into line with style(9). MFC After: 2 weeks Submitted by: Ian Lepore --- sys/dev/mii/rlphy.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/sys/dev/mii/rlphy.c b/sys/dev/mii/rlphy.c index 07acaa99cfe0..be7a0d9b163b 100644 --- a/sys/dev/mii/rlphy.c +++ b/sys/dev/mii/rlphy.c @@ -57,6 +57,11 @@ __FBSDID("$FreeBSD$"); #include "miibus_if.h" +struct rlphy_softc { + struct mii_softc sc_mii; /* generic PHY */ + int sc_is_RTL8201L; /* is an external RTL8201L PHY */ +}; + static int rlphy_probe(device_t); static int rlphy_attach(device_t); @@ -74,7 +79,7 @@ static devclass_t rlphy_devclass; static driver_t rlphy_driver = { "rlphy", rlphy_methods, - sizeof(struct mii_softc) + sizeof(struct rlphy_softc) }; DRIVER_MODULE(rlphy, miibus, rlphy_driver, rlphy_devclass, 0, 0); @@ -118,12 +123,21 @@ rlphy_attach(device_t dev) struct mii_softc *sc; struct mii_attach_args *ma; struct mii_data *mii; + struct rlphy_softc *rsc; sc = device_get_softc(dev); ma = device_get_ivars(dev); sc->mii_dev = device_get_parent(dev); mii = device_get_softc(sc->mii_dev); + /* + * Check whether we're the RTL8201L PHY and remember so the status + * routine can query the proper register for speed detection. + */ + rsc = (struct rlphy_softc *)sc; + if (mii_phy_dev_probe(dev, rlphys, BUS_PROBE_DEFAULT) == 0) + rsc->sc_is_RTL8201L++; + /* * The RealTek PHY can never be isolated, so never allow non-zero * instances! @@ -210,6 +224,7 @@ rlphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) static void rlphy_status(struct mii_softc *phy) { + struct rlphy_softc *rsc =(struct rlphy_softc *)phy; struct mii_data *mii = phy->mii_pdata; struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int bmsr, bmcr, anlpar; @@ -286,7 +301,7 @@ rlphy_status(struct mii_softc *phy) * can test the 'SPEED10' bit of the MAC's media status * register. */ - if (strcmp(mii->mii_ifp->if_dname, "rl") != 0) { + if (rsc->sc_is_RTL8201L) { if (PHY_READ(phy, 0x0019) & 0x01) mii->mii_media_active |= IFM_100_TX; else