Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 26 Apr 2015 17:48:16 +0000 (UTC)
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r282034 - projects/ifnet/sys/dev/xl
Message-ID:  <201504261748.t3QHmG7O064644@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: glebius
Date: Sun Apr 26 17:48:15 2015
New Revision: 282034
URL: https://svnweb.freebsd.org/changeset/base/282034

Log:
  Convert xl(4) to new media and miibus KPI.
  
  xl(4) supports a zillion of varieties of 3Com NICs, so it is quite complex.
  Some NICs have miibus(4), and some not. Some miibus NICs have extra mediae,
  that are added from the NIC driver on top of phys mediae.
  
  So, unlike in other NIC drivers, the mediae list isn't static, but allocated
  per-softc.  Actually it is possible to build a set of static mediae arrays,
  matching every possible NIC, but such approach would require testing on every
  possible NIC.
  
  Functional changes:
  o Since not tested on miibus(4) based xl(4), be conservative and
    don't declare IFCAP_LINKSTATE.
  
  Tested:		3Com 3c900B-COMBO Etherlink XL, only UTP tested
  Sponsored by:	Netflix
  Sponsored by:	Nginx, Inc.

Modified:
  projects/ifnet/sys/dev/xl/if_xl.c
  projects/ifnet/sys/dev/xl/if_xlreg.h
  projects/ifnet/sys/dev/xl/xlphy.c

Modified: projects/ifnet/sys/dev/xl/if_xl.c
==============================================================================
--- projects/ifnet/sys/dev/xl/if_xl.c	Sun Apr 26 17:27:55 2015	(r282033)
+++ projects/ifnet/sys/dev/xl/if_xl.c	Sun Apr 26 17:48:15 2015	(r282034)
@@ -250,7 +250,7 @@ static void xl_setwol(struct xl_softc *)
 static int xl_poll(if_t, enum poll_cmd cmd, int count);
 #endif
 
-static int xl_ifmedia_upd(if_t);
+static int xl_ifmedia_upd(if_t, if_media_t);
 static void xl_ifmedia_sts(if_t, struct ifmediareq *);
 
 static int xl_eeprom_wait(struct xl_softc *);
@@ -260,14 +260,14 @@ static void xl_rxfilter(struct xl_softc 
 static void xl_rxfilter_90x(struct xl_softc *);
 static void xl_rxfilter_90xB(struct xl_softc *);
 static void xl_setcfg(struct xl_softc *);
-static void xl_setmode(struct xl_softc *, int);
+static void xl_setmode(struct xl_softc *, if_media_t);
 static void xl_reset(struct xl_softc *);
 static int xl_list_rx_init(struct xl_softc *);
 static int xl_list_tx_init(struct xl_softc *);
 static int xl_list_tx_init_90xB(struct xl_softc *);
 static void xl_wait(struct xl_softc *);
 static void xl_mediacheck(struct xl_softc *);
-static void xl_choose_media(struct xl_softc *sc, int *media);
+static void xl_choose_media(struct xl_softc *, if_media_t *);
 static void xl_choose_xcvr(struct xl_softc *, int);
 static void xl_dma_map_addr(void *, bus_dma_segment_t *, int, int);
 #ifdef notdef
@@ -331,6 +331,8 @@ static struct ifdriver xl_ifdrv = {
 	.ifdrv_ops = {
 		.ifop_ioctl = xl_ioctl,
 		.ifop_transmit = xl_transmit,
+		.ifop_media_change = xl_ifmedia_upd,
+		.ifop_media_status = xl_ifmedia_sts,
 #ifdef DEVICE_POLLING
 		.ifop_poll = xl_poll,
 #endif
@@ -474,19 +476,16 @@ xl_miibus_statchg(device_t dev)
 			macctl &= ~XL_MACCTRL_FLOW_CONTROL_ENB;
 	}
 	CSR_WRITE_1(sc, XL_W3_MAC_CTRL, macctl);
-	if (sc->xl_ifp != NULL) {
-		if_setbaudrate(sc->xl_ifp,
-		    ifmedia_baudrate(mii->mii_media_active));
-		if_link_state_change(sc->xl_ifp,
-		    ifmedia_link_state(mii->mii_media_status));
-	}
+	if (sc->xl_ifp != NULL)
+		if_media_status(sc->xl_ifp,
+		    mii->mii_media_active | mii->mii_media_status);
 }
 
 /*
  * Special support for the 3c905B-COMBO. This card has 10/100 support
  * plus BNC and AUI ports. This means we will have both an miibus attached
  * plus some non-MII media settings. In order to allow this, we have to
- * add the extra media to the miibus's ifmedia struct, but we can't do
+ * add the extra media to the miibus's mii_data struct, but we can't do
  * that during xl_attach() because the miibus hasn't been attached yet.
  * So instead, we wait until the miibus probe/attach is done, at which
  * point we will get a callback telling is that it's safe to add our
@@ -497,11 +496,9 @@ xl_miibus_mediainit(device_t dev)
 {
 	struct xl_softc		*sc;
 	struct mii_data		*mii;
-	struct ifmedia		*ifm;
 
 	sc = device_get_softc(dev);
 	mii = device_get_softc(sc->xl_miibus);
-	ifm = &mii->mii_media;
 
 	if (sc->xl_media & (XL_MEDIAOPT_AUI | XL_MEDIAOPT_10FL)) {
 		/*
@@ -511,23 +508,22 @@ xl_miibus_mediainit(device_t dev)
 		    sc->xl_media == XL_MEDIAOPT_10FL) {
 			if (bootverbose)
 				device_printf(sc->xl_dev, "found 10baseFL\n");
-			ifmedia_add(ifm, IFM_ETHER | IFM_10_FL, 0, NULL);
-			ifmedia_add(ifm, IFM_ETHER | IFM_10_FL|IFM_HDX, 0,
-			    NULL);
+			mii_phy_add_media(mii, IFM_ETHER | IFM_10_FL);
+			mii_phy_add_media(mii, IFM_ETHER | IFM_10_FL | IFM_HDX);
 			if (sc->xl_caps & XL_CAPS_FULL_DUPLEX)
-				ifmedia_add(ifm,
-				    IFM_ETHER | IFM_10_FL | IFM_FDX, 0, NULL);
+				mii_phy_add_media(mii,
+				    IFM_ETHER | IFM_10_FL | IFM_FDX);
 		} else {
 			if (bootverbose)
 				device_printf(sc->xl_dev, "found AUI\n");
-			ifmedia_add(ifm, IFM_ETHER | IFM_10_5, 0, NULL);
+			mii_phy_add_media(mii, IFM_ETHER | IFM_10_5);
 		}
 	}
 
 	if (sc->xl_media & XL_MEDIAOPT_BNC) {
 		if (bootverbose)
 			device_printf(sc->xl_dev, "found BNC\n");
-		ifmedia_add(ifm, IFM_ETHER | IFM_10_2, 0, NULL);
+		mii_phy_add_media(mii, IFM_ETHER | IFM_10_2);
 	}
 }
 
@@ -740,7 +736,7 @@ xl_setcfg(struct xl_softc *sc)
 }
 
 static void
-xl_setmode(struct xl_softc *sc, int media)
+xl_setmode(struct xl_softc *sc, if_media_t media)
 {
 	u_int32_t		icfg;
 	u_int16_t		mediastat;
@@ -1069,13 +1065,14 @@ xl_attach(device_t dev)
 		.ifat_version = IF_ATTACH_VERSION,
 		.ifat_drv = &xl_ifdrv,
 		.ifat_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST,
-		.ifat_capabilities = IFCAP_VLAN_MTU | IFCAP_LINKSTATE,
+		.ifat_capabilities = IFCAP_VLAN_MTU,
 	};
 	u_char			eaddr[ETHER_ADDR_LEN];
 	u_int16_t		sinfo2, xcvr[2];
 	struct xl_softc		*sc;
 	if_t			ifp;
-	int			media, pmcap;
+	if_media_t		media;
+	int			midx, pmcap;
 	int			error = 0, rid, res, unit;
 	uint16_t		did;
 
@@ -1086,8 +1083,6 @@ xl_attach(device_t dev)
 
 	mtx_init(&sc->xl_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
 	    MTX_DEF);
-	ifmedia_init(&sc->ifmedia, 0, xl_ifmedia_upd, xl_ifmedia_sts);
-
 	did = pci_get_device(dev);
 
 	sc->xl_flags = 0;
@@ -1372,15 +1367,17 @@ xl_attach(device_t dev)
 		phy = MII_PHY_ANY;
 		if ((sc->xl_flags & XL_FLAG_PHYOK) == 0)
 			phy = 24;
-		error = mii_attach(dev, &sc->xl_miibus, xl_ifmedia_upd,
-		    xl_ifmedia_sts, BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY,
+		error = mii_attach(dev, &sc->xl_miibus, BMSR_DEFCAPMASK, phy,
+		    MII_OFFSET_ANY,
 		    sc->xl_type == XL_TYPE_905B ? MIIF_DOPAUSE : 0);
 		if (error != 0) {
 			device_printf(dev, "attaching PHYs failed\n");
 			goto fail;
 		}
 		mii = device_get_softc(sc->xl_miibus);
-		ifat.ifat_baudrate = ifmedia_baudrate(mii->mii_media_active);
+		ifat.ifat_mediae = mii->mii_mediae;
+		ifat.ifat_media = mii->mii_media;
+		ifat.ifat_mediamask = MII_MEDIA_MASK;
 		ifat.ifat_capabilities |= IFCAP_LINKSTATE;
 		goto media_done;
 	}
@@ -1396,14 +1393,14 @@ xl_attach(device_t dev)
 	/*
 	 * Do ifmedia setup.
 	 */
+	midx = 0;
 	if (sc->xl_media & XL_MEDIAOPT_BT) {
 		if (bootverbose)
 			device_printf(dev, "found 10baseT\n");
-		ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
-		ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_HDX, 0, NULL);
+		sc->xl_mediae[midx++] = IFM_ETHER | IFM_10_T;
+		sc->xl_mediae[midx++] = IFM_ETHER | IFM_10_T | IFM_HDX;
 		if (sc->xl_caps & XL_CAPS_FULL_DUPLEX)
-			ifmedia_add(&sc->ifmedia,
-			    IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
+			sc->xl_mediae[midx++] = IFM_ETHER | IFM_10_T | IFM_FDX;
 	}
 
 	if (sc->xl_media & (XL_MEDIAOPT_AUI|XL_MEDIAOPT_10FL)) {
@@ -1414,37 +1411,35 @@ xl_attach(device_t dev)
 		    sc->xl_media == XL_MEDIAOPT_10FL) {
 			if (bootverbose)
 				device_printf(dev, "found 10baseFL\n");
-			ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_FL, 0, NULL);
-			ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_FL|IFM_HDX,
-			    0, NULL);
+			sc->xl_mediae[midx++] = IFM_ETHER | IFM_10_FL;
+			sc->xl_mediae[midx++] = IFM_ETHER | IFM_10_FL | IFM_HDX;
 			if (sc->xl_caps & XL_CAPS_FULL_DUPLEX)
-				ifmedia_add(&sc->ifmedia,
-				    IFM_ETHER|IFM_10_FL|IFM_FDX, 0, NULL);
+				sc->xl_mediae[midx++] = 
+				    IFM_ETHER | IFM_10_FL | IFM_FDX;
 		} else {
 			if (bootverbose)
 				device_printf(dev, "found AUI\n");
-			ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_5, 0, NULL);
+			sc->xl_mediae[midx++] = IFM_ETHER | IFM_10_5;
 		}
 	}
 
 	if (sc->xl_media & XL_MEDIAOPT_BNC) {
 		if (bootverbose)
 			device_printf(dev, "found BNC\n");
-		ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_2, 0, NULL);
+		sc->xl_mediae[midx++] = IFM_ETHER | IFM_10_2;
 	}
 
 	if (sc->xl_media & XL_MEDIAOPT_BFX) {
 		if (bootverbose)
 			device_printf(dev, "found 100baseFX\n");
-		ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_FX, 0, NULL);
+		sc->xl_mediae[midx++] = IFM_ETHER | IFM_100_FX;
 	}
 
 	media = IFM_ETHER|IFM_100_TX|IFM_FDX;
 	xl_choose_media(sc, &media);
 
-	if (sc->xl_miibus == NULL)
-		ifmedia_set(&sc->ifmedia, media);
-	ifat.ifat_baudrate = ifmedia_baudrate(sc->ifmedia.ifm_media);
+	ifat.ifat_mediae = sc->xl_mediae;
+	ifat.ifat_media = media;
 
 media_done:
 	if (sc->xl_flags & XL_FLAG_NO_XCVR_PWR) {
@@ -1494,7 +1489,7 @@ fail:
  *     satisfy lock assertions.
  */
 static void
-xl_choose_media(struct xl_softc *sc, int *media)
+xl_choose_media(struct xl_softc *sc, if_media_t *media)
 {
 
 	XL_LOCK(sc);
@@ -1579,7 +1574,6 @@ xl_detach(device_t dev)
 	if (sc->xl_miibus)
 		device_delete_child(dev, sc->xl_miibus);
 	bus_generic_detach(dev);
-	ifmedia_removeall(&sc->ifmedia);
 
 	if (sc->xl_intrhand)
 		bus_teardown_intr(dev, sc->xl_irq, sc->xl_intrhand);
@@ -2625,7 +2619,7 @@ static void
 xl_init(struct xl_softc *sc)
 {
 	int			error, i;
-	struct mii_data		*mii = NULL;
+	struct mii_data		*mii;
 
 	XL_LOCK_ASSERT(sc);
 
@@ -2647,9 +2641,6 @@ xl_init(struct xl_softc *sc)
 	xl_wait(sc);
 	DELAY(10000);
 
-	if (sc->xl_miibus != NULL)
-		mii = device_get_softc(sc->xl_miibus);
-
 	/*
 	 * Clear WOL status and disable all WOL feature as WOL
 	 * would interfere Rx operation under normal environments.
@@ -2812,8 +2803,10 @@ xl_init(struct xl_softc *sc)
 	xl_wait(sc);
 
 	/* XXX Downcall to miibus. */
-	if (mii != NULL)
-		mii_mediachg(mii);
+	if (sc->xl_miibus != NULL) {
+		mii = device_get_softc(sc->xl_miibus);
+		mii_mediachg(mii, mii->mii_media);
+	}
 
 	/* Select window 7 for normal operations. */
 	XL_SEL_WIN(7);
@@ -2828,10 +2821,9 @@ xl_init(struct xl_softc *sc)
  * Set media options.
  */
 static int
-xl_ifmedia_upd(if_t ifp)
+xl_ifmedia_upd(if_t ifp, if_media_t media)
 {
 	struct xl_softc		*sc;
-	struct ifmedia		*ifm = NULL;
 	struct mii_data		*mii = NULL;
 
 	sc = if_getsoftc(ifp, IF_DRIVER_SOFTC);
@@ -2839,17 +2831,13 @@ xl_ifmedia_upd(if_t ifp)
 
 	if (sc->xl_miibus != NULL)
 		mii = device_get_softc(sc->xl_miibus);
-	if (mii == NULL)
-		ifm = &sc->ifmedia;
-	else
-		ifm = &mii->mii_media;
 
-	switch (IFM_SUBTYPE(ifm->ifm_media)) {
+	switch (IFM_SUBTYPE(media)) {
 	case IFM_100_FX:
 	case IFM_10_FL:
 	case IFM_10_2:
 	case IFM_10_5:
-		xl_setmode(sc, ifm->ifm_media);
+		xl_setmode(sc, media);
 		XL_UNLOCK(sc);
 		return (0);
 	}
@@ -2860,7 +2848,7 @@ xl_ifmedia_upd(if_t ifp)
 		sc->xl_flags &= ~XL_FLAG_RUNNING;
 		xl_init(sc);
 	} else {
-		xl_setmode(sc, ifm->ifm_media);
+		xl_setmode(sc, media);
 	}
 
 	XL_UNLOCK(sc);
@@ -2951,7 +2939,6 @@ xl_ioctl(if_t ifp, u_long command, void 
 	struct ifreq		*ifr = (struct ifreq *) data;
 	uint32_t		oflags;
 	int			error = 0;
-	struct mii_data		*mii = NULL;
 
 	sc = if_getsoftc(ifp, IF_DRIVER_SOFTC);
 
@@ -2979,17 +2966,6 @@ xl_ioctl(if_t ifp, u_long command, void 
 			xl_rxfilter(sc);
 		XL_UNLOCK(sc);
 		break;
-	case SIOCGIFMEDIA:
-	case SIOCSIFMEDIA:
-		if (sc->xl_miibus != NULL)
-			mii = device_get_softc(sc->xl_miibus);
-		if (mii == NULL)
-			error = ifmedia_ioctl(ifp, ifr,
-			    &sc->ifmedia, command);
-		else
-			error = ifmedia_ioctl(ifp, ifr,
-			    &mii->mii_media, command);
-		break;
 	case SIOCSIFCAP:
 #ifdef DEVICE_POLLING
 		if (((ifr->ifr_reqcap ^ ifr->ifr_curcap) & IFCAP_POLLING)) {

Modified: projects/ifnet/sys/dev/xl/if_xlreg.h
==============================================================================
--- projects/ifnet/sys/dev/xl/if_xlreg.h	Sun Apr 26 17:27:55 2015	(r282033)
+++ projects/ifnet/sys/dev/xl/if_xlreg.h	Sun Apr 26 17:48:15 2015	(r282034)
@@ -589,14 +589,12 @@ struct xl_type {
 struct xl_softc {
 	if_t			xl_ifp;	/* interface info */
 	device_t		xl_dev;		/* device info */
-	struct ifmedia		ifmedia;	/* media info */
 	bus_space_handle_t	xl_bhandle;
 	bus_space_tag_t		xl_btag;
 	void			*xl_intrhand;
 	struct resource		*xl_irq;
 	struct resource		*xl_res;
 	device_t		xl_miibus;
-	const struct xl_type	*xl_info;	/* 3Com adapter info */
 	bus_dma_tag_t		xl_mtag;
 	bus_dmamap_t		xl_tmpmap;	/* spare DMA map */
 	u_int8_t		xl_type;
@@ -620,6 +618,8 @@ struct xl_softc {
 #ifdef DEVICE_POLLING
 	int			rxcycles;
 #endif
+#define	XL_MAX_MEDIAE 10
+	if_media_t		xl_mediae[XL_MAX_MEDIAE + 1];
 };
 
 #define XL_LOCK(_sc)		mtx_lock(&(_sc)->xl_mtx)

Modified: projects/ifnet/sys/dev/xl/xlphy.c
==============================================================================
--- projects/ifnet/sys/dev/xl/xlphy.c	Sun Apr 26 17:27:55 2015	(r282033)
+++ projects/ifnet/sys/dev/xl/xlphy.c	Sun Apr 26 17:48:15 2015	(r282034)
@@ -99,8 +99,9 @@ static driver_t xlphy_driver = {
 
 DRIVER_MODULE(xlphy, miibus, xlphy_driver, xlphy_devclass, 0, 0);
 
-static int	xlphy_service(struct mii_softc *, struct mii_data *, int);
-static void	xlphy_reset(struct mii_softc *);
+static int	xlphy_service(struct mii_softc *, struct mii_data *, mii_cmd_t,
+		    if_media_t);
+static void	xlphy_reset(struct mii_softc *, if_media_t);
 
 /*
  * Some 3Com internal PHYs report zero for OUI and model, others use
@@ -144,7 +145,8 @@ xlphy_attach(device_t dev)
 }
 
 static int
-xlphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
+xlphy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd,
+    if_media_t ifm)
 {
 
 	switch (cmd) {
@@ -152,7 +154,7 @@ xlphy_service(struct mii_softc *sc, stru
 		break;
 
 	case MII_MEDIACHG:
-		mii_phy_setmedia(sc);
+		mii_phy_setmedia(sc, ifm);
 		break;
 
 	case MII_TICK:
@@ -164,7 +166,7 @@ xlphy_service(struct mii_softc *sc, stru
 	}
 
 	/* Update the media status. */
-	PHY_STATUS(sc);
+	PHY_STATUS(sc, ifm);
 
 	/* Callback if something changed. */
 	mii_phy_update(sc, cmd);
@@ -172,10 +174,10 @@ xlphy_service(struct mii_softc *sc, stru
 }
 
 static void
-xlphy_reset(struct mii_softc *sc)
+xlphy_reset(struct mii_softc *sc, if_media_t media)
 {
 
-	mii_phy_reset(sc);
+	mii_phy_reset(sc, media);
 
 	/*
 	 * XXX 3Com PHY doesn't set the BMCR properly after



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201504261748.t3QHmG7O064644>