With the growing popularity of SoCs, external PHYs are making a bit of a comeback. In quite a few cases I'm seeing rgephy(4) show up twice, once on address 0 and once on some other address. But there is only one PHY soldered onto the board. This is a little bit annoying but mostly harmless. The mii(4) layer will use the first one that shows up and everything works. But now I'm seeing the same thing happening with a Micrel PHY that shows up as ukphy(4). And here it is causing issues since the mii(4) attempts to "isolate" PHYs that it isn't using and the Micrel PHY actually implements that functionality.
One way to solve the issue is to add the MIIF_NOISOLATE flag to the mii_attach() call. However that still means the PHY shows up twice in dmesg. So here is an alternative solution. The mii_attach() function has an offloc argument that kan be used to tell the mii(4) layer to attach the first, second, third, etc. PHY it finds when scanning the bus. The diff below makes dwge(4) set offloc to 0 (to attach the first PHY found) if phyloc is set to MII_PHY_ANY. This means we attach the PHY with address 0 instead of its real address, but that is ok. This code is a little bit ugly. An alternative would be to modify mii_attach(4) such that it no longer panics if phyloc != MII_PHY_ANY and offloc != MII_OFFSET_ANY. Then we could simply set offloc to 0 in the mii_attach() call. comments? ok? Index: dev/ic/dwc_gmac.c =================================================================== RCS file: /cvs/src/sys/dev/ic/dwc_gmac.c,v retrieving revision 1.8 diff -u -p -r1.8 dwc_gmac.c --- dev/ic/dwc_gmac.c 29 Jun 2017 17:36:16 -0000 1.8 +++ dev/ic/dwc_gmac.c 4 Apr 2018 09:47:29 -0000 @@ -222,8 +222,8 @@ dwc_gmac_attach(struct dwc_gmac_softc *s ifmedia_init(&mii->mii_media, 0, dwc_gmac_ifmedia_upd, dwc_gmac_ifmedia_sts); - mii_attach((void *)sc, mii, 0xffffffff, phyloc, MII_OFFSET_ANY, - MIIF_DOPAUSE); + mii_attach((void *)sc, mii, 0xffffffff, phyloc, + (phyloc == MII_PHY_ANY) ? 0 : MII_OFFSET_ANY, MIIF_DOPAUSE); if (LIST_EMPTY(&mii->mii_phys)) { printf("%s: no PHY found!\n", sc->sc_dev.dv_xname);