Date: Fri, 6 Jan 2012 14:03:27 +0100 From: Stefan Bethke <stb@lassitu.de> To: Marius Strobl <marius@alchemy.franken.de> Cc: freebsd-arch@freebsd.org Subject: Re: Extending sys/dev/mii Message-ID: <331547BD-7CFD-40B3-97C0-2C85B31D03FB@lassitu.de> In-Reply-To: <47ABA638-7E08-4350-A03C-3D4A23BF2D7E@lassitu.de> References: <8D025847-4BE4-4B2C-87D7-97E72CC9D325@lassitu.de> <20120104215930.GM90831@alchemy.franken.de> <47ABA638-7E08-4350-A03C-3D4A23BF2D7E@lassitu.de>
next in thread | previous in thread | raw e-mail | index | archive | help
--Apple-Mail-3--344543017 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii (Now with actual patch attached. Thanks ray!) Am 05.01.2012 um 21:52 schrieb Stefan Bethke: > The problem with this is that the miibus instance might not be a = (transitive) child of the ethernet driver that has the MII that needs to = be adjusted to the new PHY settings. And since the method does not = provide any parameters about which phy or miibus did issue the method, = or which ifp it applies to, bubbling it up won't work (that the scenario = where the PHY for arge0 is connected to the switch's MDIO, which is = attached to arge1's MDIO). >=20 >>> Since the parent will now be the mdiobus, miibus needs effectively = two attachments, one to the provider of the MDIO access, the other for = the ethernet interface. I propose to associate the ethernet interface = by a modified mii_attach() function that takes a device_t (of the = ethernet driver) instead of the two callback function pointers. >>=20 >> Please elaborate on why these changes are technically necessary >> to implement what you are trying do. Otherwise I prefer to avoid >> them given the rototilling they'd cause. >=20 > Necessary is a strong word. Right now, I'm trying to understand how a = sensible change would even look like, and which combination of glue code = and miibus changes make the most sense. >=20 > Let me see if I can come up with a prototype patch the next couple of = days, so we don't have to theorize about the changes that might or might = not be necessary. Here's a patch that causes zero rototilling, if I'm not mistaken. The patch implements the split between the MDIO access and notifications = posted to the ethernet interface device that has the MII that needs to = be adjusted in accordance with the PHY autonegotiation results. I've = added a field to the ivars struct and not the softc, because the softc = is included by many network drivers, while the ivars are private to = mii.c For this reason, I believe this change is API and ABI compatible, = and likely can be MFCed. (I believe MFCing is not high on the priority = list because many other parts in sys/mips would need to be MFCed first = for all the Atheros platforms to become fully usable, but Adrian can = correct me.) A second patch will implement a separate MDIO bus driver, but I haven't = finished that yet. It s completely independent of the above change. Stefan --=20 Stefan Bethke <stb@lassitu.de> Fon +49 151 14070811 --Apple-Mail-3--344543017 Content-Disposition: attachment; filename=mii.diff Content-Type: application/octet-stream; name="mii.diff" Content-Transfer-Encoding: 7bit diff --git a/sys/dev/mii/mii.c b/sys/dev/mii/mii.c index f85c579..ef9421b 100644 --- a/sys/dev/mii/mii.c +++ b/sys/dev/mii/mii.c @@ -106,6 +106,7 @@ driver_t miibus_driver = { struct miibus_ivars { struct ifnet *ifp; + device_t ifdev; ifm_change_cb_t ifmedia_upd; ifm_stat_cb_t ifmedia_sts; u_int mii_flags; @@ -300,11 +301,10 @@ miibus_writereg(device_t dev, int phy, int reg, int data) static void miibus_statchg(device_t dev) { - device_t parent; + struct miibus_ivars *ivars = device_get_ivars(dev); struct mii_data *mii; - parent = device_get_parent(dev); - MIIBUS_STATCHG(parent); + MIIBUS_STATCHG(ivars->ifdev); mii = device_get_softc(dev); mii->mii_ifp->if_baudrate = ifmedia_baudrate(mii->mii_media_active); @@ -313,12 +313,11 @@ miibus_statchg(device_t dev) static void miibus_linkchg(device_t dev) { + struct miibus_ivars *ivars = device_get_ivars(dev); struct mii_data *mii; - device_t parent; int link_state; - parent = device_get_parent(dev); - MIIBUS_LINKCHG(parent); + MIIBUS_LINKCHG(ivars->ifdev); mii = device_get_softc(dev); @@ -335,12 +334,13 @@ miibus_linkchg(device_t dev) static void miibus_mediainit(device_t dev) { + struct miibus_ivars *ivars = device_get_ivars(dev); struct mii_data *mii; struct ifmedia_entry *m; int media = 0; - /* Poke the parent in case it has any media of its own to add. */ - MIIBUS_MEDIAINIT(device_get_parent(dev)); + /* Poke the interface device in case it has any media of its own to add. */ + MIIBUS_MEDIAINIT(ivars->ifdev); mii = device_get_softc(dev); LIST_FOREACH(m, &mii->mii_media.ifm_list, ifm_list) { @@ -361,6 +361,22 @@ mii_attach(device_t dev, device_t *miibus, struct ifnet *ifp, ifm_change_cb_t ifmedia_upd, ifm_stat_cb_t ifmedia_sts, int capmask, int phyloc, int offloc, int flags) { + return mii_attach_interface(dev, dev, miibus, ifp, ifmedia_upd, + ifmedia_sts, capmask, phyloc, offloc, flags); +} + +/* + * Helper function used by network interface drivers. The mdiodev device + * becomes the parent of the miibus and provides access to the MDIO master + * that communicates with the PHY(s). The ifdev device is the network + * interface driver that will receive MIIBUS_STATCHG, MIIBUS_LINKCHG, and + * MIIBUS_MEDIAINIT messages. Both devices can be the same. + */ +int +mii_attach_interface(device_t mdiodev, device_t ifdev, device_t *miibus, struct ifnet *ifp, + ifm_change_cb_t ifmedia_upd, ifm_stat_cb_t ifmedia_sts, int capmask, + int phyloc, int offloc, int flags) +{ struct miibus_ivars *ivars; struct mii_attach_args *args, ma; device_t *children, phy; @@ -395,10 +411,11 @@ mii_attach(device_t dev, device_t *miibus, struct ifnet *ifp, if (ivars == NULL) return (ENOMEM); ivars->ifp = ifp; + ivars->ifdev = ifdev; ivars->ifmedia_upd = ifmedia_upd; ivars->ifmedia_sts = ifmedia_sts; ivars->mii_flags = flags; - *miibus = device_add_child(dev, "miibus", -1); + *miibus = device_add_child(mdiodev, "miibus", -1); if (*miibus == NULL) { rv = ENXIO; goto fail; @@ -453,7 +470,7 @@ mii_attach(device_t dev, device_t *miibus, struct ifnet *ifp, * many braindead PHYs report 0/0 in their ID registers, * so we test for media in the BMSR. */ - bmsr = MIIBUS_READREG(dev, ma.mii_phyno, MII_BMSR); + bmsr = MIIBUS_READREG(mdiodev, ma.mii_phyno, MII_BMSR); if (bmsr == 0 || bmsr == 0xffff || (bmsr & (BMSR_EXTSTAT | BMSR_MEDIAMASK)) == 0) { /* Assume no PHY at this address. */ @@ -478,8 +495,8 @@ mii_attach(device_t dev, device_t *miibus, struct ifnet *ifp, * the `ukphy' driver, as we have no ID information to * match on. */ - ma.mii_id1 = MIIBUS_READREG(dev, ma.mii_phyno, MII_PHYIDR1); - ma.mii_id2 = MIIBUS_READREG(dev, ma.mii_phyno, MII_PHYIDR2); + ma.mii_id1 = MIIBUS_READREG(mdiodev, ma.mii_phyno, MII_PHYIDR1); + ma.mii_id2 = MIIBUS_READREG(mdiodev, ma.mii_phyno, MII_PHYIDR2); ma.mii_offset = ivars->mii_offset; args = malloc(sizeof(struct mii_attach_args), M_DEVBUF, @@ -511,7 +528,7 @@ mii_attach(device_t dev, device_t *miibus, struct ifnet *ifp, rv = ENXIO; goto fail; } - rv = bus_generic_attach(dev); + rv = bus_generic_attach(mdiodev); if (rv != 0) goto fail; @@ -526,7 +543,7 @@ mii_attach(device_t dev, device_t *miibus, struct ifnet *ifp, fail: if (*miibus != NULL) - device_delete_child(dev, *miibus); + device_delete_child(mdiodev, *miibus); free(ivars, M_DEVBUF); if (first != 0) *miibus = NULL; diff --git a/sys/dev/mii/miivar.h b/sys/dev/mii/miivar.h index 34b0e9ed..029e6a8 100644 --- a/sys/dev/mii/miivar.h +++ b/sys/dev/mii/miivar.h @@ -248,6 +248,8 @@ extern driver_t miibus_driver; int mii_attach(device_t, device_t *, struct ifnet *, ifm_change_cb_t, ifm_stat_cb_t, int, int, int, int); +int mii_attach_interface(device_t, device_t, device_t *, struct ifnet *, + ifm_change_cb_t, ifm_stat_cb_t, int, int, int, int); void mii_down(struct mii_data *); int mii_mediachg(struct mii_data *); void mii_tick(struct mii_data *); --Apple-Mail-3--344543017--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?331547BD-7CFD-40B3-97C0-2C85B31D03FB>