Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 26 Apr 2015 15:40:59 +0000 (UTC)
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r282021 - projects/ifnet/sys/net
Message-ID:  <201504261540.t3QFexFv000257@svn.freebsd.org>

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

Log:
  Tie ifmedia to the generic framework of new ifnet KPI.
  
  Implementation:
  o struct if_media goes opaque into if_media.c
  o ifmedia is an optional softc (keyword IF_MEDIA) of an interface.
  o if_media.h declares just preprocessor defines to manipulate media
    bits. Since a conservative decision was taken in r281236, the media
    information remains a single 32-bit word.
    However, to improve type checking it is declared as if_media_t, not
    a bare integer.
    if_media.h is now automatically included from if.h
  o if_attach() calls ifmedia_alloc(). if_free() calls ifmedia_free().
  
  Driver changes:
  o Drivers supply ifop_media_change and ifop_media_status callbacks in
    their ifdriver ifops. This were arguments to ifmedia_init() before.
    The ifop_media_change() callback gets additional argument of the new
    media, we are trying to swtich to.
  o On attach, drivers supply array of supported media words in ifat_mediae,
    currently chose media in ifat_media and optional ifat_mediamask.
    Drivers may change the media array later via if_media_change().
  o Drivers don't need to support SIOCSIFMEDIA, SIOCGIFMEDIA.  The stack
    does now.
  o Drivers may call if_media_status() if they are running autonegotiation
    and wish to report new status.  The function updates link state and
    baudrate of the interface.
  
  Sponsored by:	Netflix
  Sponsored by:	Nginx, Inc.

Modified:
  projects/ifnet/sys/net/if.c
  projects/ifnet/sys/net/if.h
  projects/ifnet/sys/net/if_media.c
  projects/ifnet/sys/net/if_media.h

Modified: projects/ifnet/sys/net/if.c
==============================================================================
--- projects/ifnet/sys/net/if.c	Sun Apr 26 12:24:42 2015	(r282020)
+++ projects/ifnet/sys/net/if.c	Sun Apr 26 15:40:58 2015	(r282021)
@@ -100,6 +100,11 @@
 #include <compat/freebsd32/freebsd32.h>
 #endif
 
+/* Interface media functions, living in if_media.c. */
+extern void 	ifmedia_alloc(struct ifnet *, struct if_attach_args *);
+extern void	ifmedia_free(struct ifnet *);
+extern int	ifmedia_ioctl(struct ifnet *, struct ifreq *, u_long);
+
 SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers");
 SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management");
 
@@ -543,6 +548,7 @@ if_attach(struct if_attach_args *ifat)
 	mac_ifnet_init(ifp);
 	mac_ifnet_create(ifp);
 #endif
+	rw_init(&ifp->if_lock, "if_lock");
 
 	ifp->if_ops = &ifdrv->ifdrv_ops;
 	ifp->if_drv = ifdrv;
@@ -558,6 +564,13 @@ if_attach(struct if_attach_args *ifat)
 	COPY(baudrate);
 #undef COPY
 
+	if (ifat->ifat_mediae) {
+		KASSERT(ifp->if_ops->ifop_media_change != NULL &&
+		    ifp->if_ops->ifop_media_status != NULL,
+		    ("%s: media array but no callbacks", ifdrv->ifdrv_name));
+		ifmedia_alloc(ifp, ifat);
+	}
+
 	if (ifat->ifat_tsomax) {
 		/*
 		 * Driver wants dynamic tsomax on this interface, we
@@ -578,7 +591,6 @@ if_attach(struct if_attach_args *ifat)
 	if (ifdrv->ifdrv_maxqlen > 0)
 		ifp->if_snd = if_snd_alloc(ifdrv->ifdrv_maxqlen);
 
-	rw_init(&ifp->if_lock, "if_lock");
 	IF_AFDATA_LOCK_INIT(ifp);
 	TASK_INIT(&ifp->if_linktask, 0, do_link_state_change, ifp);
 	TAILQ_INIT(&ifp->if_addrhead);
@@ -670,6 +682,8 @@ if_free_internal(struct ifnet *ifp)
 	if (ifp->if_tsomax != ifp->if_drv->ifdrv_tsomax)
 		free(ifp->if_tsomax, M_IFNET);
 
+	ifmedia_free(ifp);
+
 	free(ifp, M_IFNET);
 }
 
@@ -2749,7 +2763,6 @@ if_drvioctl(struct ifnet *ifp, u_long cm
 #ifdef INET6
 	case SIOCSIFPHYADDR_IN6:
 #endif
-	case SIOCSIFMEDIA:
 	case SIOCSIFGENERIC:
 		error = priv_check(td, PRIV_NET_HWIOCTL);
 		if (error)
@@ -2762,8 +2775,6 @@ if_drvioctl(struct ifnet *ifp, u_long cm
 	case SIOCGIFSTATUS:
 	case SIOCGIFPSRCADDR:
 	case SIOCGIFPDSTADDR:
-	case SIOCGIFMEDIA:
-	case SIOCGIFXMEDIA:
 	case SIOCGIFGENERIC:
 		error = if_ioctl(ifp, cmd, data, td);
 		break;
@@ -2806,6 +2817,15 @@ if_drvioctl(struct ifnet *ifp, u_long cm
 		break;
 	}
 
+	case SIOCSIFMEDIA:
+		error = priv_check(td, PRIV_NET_HWIOCTL);
+		if (error)
+			return (error);
+		/* FALLTHROUGH */
+	case SIOCGIFMEDIA:
+	case SIOCGIFXMEDIA:
+		return (ifmedia_ioctl(ifp, ifr, cmd));
+
 	default:
 		error = ENOIOCTL;
 		break;

Modified: projects/ifnet/sys/net/if.h
==============================================================================
--- projects/ifnet/sys/net/if.h	Sun Apr 26 12:24:42 2015	(r282020)
+++ projects/ifnet/sys/net/if.h	Sun Apr 26 15:40:58 2015	(r282021)
@@ -539,6 +539,7 @@ __END_DECLS
 
 #ifdef _KERNEL
 #include <net/if_types.h>
+#include <net/if_media.h>
 /*
  * Under _KERNEL there live declarations from net/if.c, that are public
  * and available to network device drivers.  Declarations that are protected
@@ -586,6 +587,7 @@ typedef enum {
 	IF_CARP,
 	IF_VLAN,
 	IF_TOEDEV,
+	IF_MEDIA,
 	/*
 	 * Space above 99999 is split among different vendors.
 	 *
@@ -603,6 +605,8 @@ typedef int	(*if_output_t)(if_t, struct 
 typedef int	(*if_ioctl_t)(if_t, u_long, void *, struct thread *);
 typedef uint64_t (*if_get_counter_t)(if_t, ift_counter);
 typedef void	(*if_qflush_t)(if_t);
+typedef int	(*if_media_change_t)(if_t, if_media_t);
+typedef void	(*if_media_status_t)(if_t, struct ifmediareq *);
 typedef int	(*if_resolvemulti_t)(if_t, struct sockaddr **,
     struct sockaddr *);
 typedef void	(*if_reassign_t)(if_t, struct vnet *);
@@ -623,6 +627,8 @@ struct ifops {
 	if_ioctl_t	ifop_ioctl;	/* ioctl routine */
 	if_get_counter_t ifop_get_counter; /* get counter values */
 	if_qflush_t	ifop_qflush;	/* flush any queue */	
+	if_media_change_t ifop_media_change; /* change media */
+	if_media_status_t ifop_media_status; /* query media */
 	if_resolvemulti_t ifop_resolvemulti; /* validate/resolve multicast */
 	if_reassign_t	ifop_reassign;	/* reassign to vnet routine */
 	if_vlan_event_t	ifop_vlan_event;/* VLAN config/unconfig */
@@ -694,11 +700,18 @@ struct if_attach_args {
 #define	IFAT_DUNIT_NONE	(-1)
 	char *		ifat_name;	/* If driver wants a specific name. */
 	/*
-	 * Variables that may differ between two instances of a same
-	 * driver, but are constant within instance lifetime.
+	 * Capabilities can be different for two interfaces of the same
+	 * driver, e.g. different chip revisions.
 	 */
 	uint64_t	ifat_capabilities;
 	/*
+	 * Pointer to static array of supported mediae, current media
+	 * word, and ignore mask for ifmedia_match().
+	 */
+	if_media_t	*ifat_mediae;
+	if_media_t	ifat_media;
+	if_media_t	ifat_mediamask;
+	/*
 	 * MTU, flags, capabilities at attach time.  Driver
 	 * can change them later.
 	 */
@@ -732,6 +745,12 @@ int	if_drvioctl(if_t, u_long, void *, st
 uint64_t if_get_counter_default(if_t, ift_counter);
 
 /*
+ * Interface media manipulation by drivers.
+ */
+void	if_media_status(if_t, if_media_t);
+void	if_media_change(if_t, if_media_t *, if_media_t);
+
+/*
  * Interface if_ops that are available for drivers.
  */
 void	if_input_noinline(if_t, struct mbuf *);

Modified: projects/ifnet/sys/net/if_media.c
==============================================================================
--- projects/ifnet/sys/net/if_media.c	Sun Apr 26 12:24:42 2015	(r282020)
+++ projects/ifnet/sys/net/if_media.c	Sun Apr 26 15:40:58 2015	(r282021)
@@ -1,6 +1,3 @@
-/*	$NetBSD: if_media.c,v 1.1 1997/03/17 02:55:15 thorpej Exp $	*/
-/* $FreeBSD$ */
-
 /*-
  * Copyright (c) 1997
  *	Jonathan Stone and Jason R. Thorpe.  All rights reserved.
@@ -33,218 +30,106 @@
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- */
-
-/*
- * BSD/OS-compatible network interface media selection.
  *
- * Where it is safe to do so, this code strays slightly from the BSD/OS
- * design.  Software which uses the API (device drivers, basically)
- * shouldn't notice any difference.
- *
- * Many thanks to Matt Thomas for providing the information necessary
- * to implement this interface.
+ * $NetBSD: if_media.c,v 1.1 1997/03/17 02:55:15 thorpej Exp $
  */
 
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 #include "opt_ifmedia.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
+#include <sys/kernel.h>
 #include <sys/malloc.h>
 #include <sys/module.h>
 #include <sys/sysctl.h>
 
 #include <net/if.h>
-#include <net/if_media.h>
+#include <net/if_var.h>
 
-/*
- * Compile-time options:
- * IFMEDIA_DEBUG:
- *	turn on implementation-level debug printfs.
- * 	Useful for debugging newly-ported  drivers.
- */
+static MALLOC_DEFINE(M_IFMEDIA, "if_media", "interface media info");
 
-static struct ifmedia_entry *ifmedia_match(struct ifmedia *ifm,
-    int flags, int mask);
+struct ifmedia {
+	if_media_t      ifm_media;	/* current user-set media word */
+	if_media_t      ifm_mask;	/* mask of changes we don't care */
+	if_media_t      *ifm_array;	/* array of all supported mediae */
+	if_media_t	*ifm_cur;	/* currently selected media */
+};
 
+void 	ifmedia_alloc(struct ifnet *, struct if_attach_args *);
+void 	ifmedia_free(struct ifnet *);
+int	ifmedia_ioctl(struct ifnet *, struct ifreq *, u_long);
+
+static if_media_t *	ifmedia_match(struct ifmedia *, if_media_t);
+static if_media_t	ifmedia_compat(if_media_t media);
+static uint64_t		ifmedia_baudrate(if_media_t);
+static int		ifmedia_link_state(u_int);
 #ifdef IFMEDIA_DEBUG
-#include <net/if_var.h>
-int	ifmedia_debug = 0;
-SYSCTL_INT(_debug, OID_AUTO, ifmedia, CTLFLAG_RW, &ifmedia_debug,
-	    0, "if_media debugging msgs");
-static	void ifmedia_printword(int);
+static void		ifmedia_printword(int);
+static int ifmedia_debug;
 #endif
 
 /*
- * Initialize if_media struct for a specific interface instance.
+ * Called by if_attach(), if interface reports media.
  */
 void
-ifmedia_init(ifm, dontcare_mask, change_callback, status_callback)
-	struct ifmedia *ifm;
-	int dontcare_mask;
-	ifm_change_cb_t change_callback;
-	ifm_stat_cb_t status_callback;
+ifmedia_alloc(struct ifnet *ifp, struct if_attach_args *ifat)
 {
-
-	LIST_INIT(&ifm->ifm_list);
-	ifm->ifm_cur = NULL;
-	ifm->ifm_media = 0;
-	ifm->ifm_mask = dontcare_mask;		/* IF don't-care bits */
-	ifm->ifm_change = change_callback;
-	ifm->ifm_status = status_callback;
-}
-
-void
-ifmedia_removeall(ifm)
-	struct ifmedia *ifm;
-{
-	struct ifmedia_entry *entry;
-
-	for (entry = LIST_FIRST(&ifm->ifm_list); entry;
-	     entry = LIST_FIRST(&ifm->ifm_list)) {
-		LIST_REMOVE(entry, ifm_list);
-		free(entry, M_IFADDR);
-	}
-}
-
-/*
- * Add a media configuration to the list of supported media
- * for a specific interface instance.
- */
-void
-ifmedia_add(ifm, mword, data, aux)
 	struct ifmedia *ifm;
-	int mword;
-	int data;
-	void *aux;
-{
-	register struct ifmedia_entry *entry;
-
-#ifdef IFMEDIA_DEBUG
-	if (ifmedia_debug) {
-		if (ifm == NULL) {
-			printf("ifmedia_add: null ifm\n");
-			return;
-		}
-		printf("Adding entry for ");
-		ifmedia_printword(mword);
-	}
-#endif
 
-	entry = malloc(sizeof(*entry), M_IFADDR, M_NOWAIT);
-	if (entry == NULL)
-		panic("ifmedia_add: can't malloc entry");
-
-	entry->ifm_media = mword;
-	entry->ifm_data = data;
-	entry->ifm_aux = aux;
+	ifm = malloc(sizeof(struct ifmedia), M_IFMEDIA, M_WAITOK);
+	ifm->ifm_array = ifat->ifat_mediae;
+	ifm->ifm_mask = ifat->ifat_mediamask;
+	ifm->ifm_cur = ifmedia_match(ifm, ifat->ifat_media);
+	ifm->ifm_media = *ifm->ifm_cur;
 
-	LIST_INSERT_HEAD(&ifm->ifm_list, entry, ifm_list);
-}
+	if_setsoftc(ifp, IF_MEDIA, ifm);
 
-/*
- * Add an array of media configurations to the list of
- * supported media for a specific interface instance.
- */
-void
-ifmedia_list_add(ifm, lp, count)
-	struct ifmedia *ifm;
-	struct ifmedia_entry *lp;
-	int count;
-{
-	int i;
-
-	for (i = 0; i < count; i++)
-		ifmedia_add(ifm, lp[i].ifm_media, lp[i].ifm_data,
-		    lp[i].ifm_aux);
+	ifp->if_baudrate = ifmedia_baudrate(ifm->ifm_media);
 }
 
 /*
- * Set the default active media. 
- *
- * Called by device-specific code which is assumed to have already
- * selected the default media in hardware.  We do _not_ call the
- * media-change callback.
+ * Called by if_free().
  */
 void
-ifmedia_set(ifm, target)
-	struct ifmedia *ifm; 
-	int target;
-
-{
-	struct ifmedia_entry *match;
-
-	match = ifmedia_match(ifm, target, ifm->ifm_mask);
-
-	if (match == NULL) {
-		printf("ifmedia_set: no match for 0x%x/0x%x\n",
-		    target, ~ifm->ifm_mask);
-		panic("ifmedia_set");
-	}
-	ifm->ifm_cur = match;
-
-#ifdef IFMEDIA_DEBUG
-	if (ifmedia_debug) {
-		printf("ifmedia_set: target ");
-		ifmedia_printword(target);
-		printf("ifmedia_set: setting to ");
-		ifmedia_printword(ifm->ifm_cur->ifm_media);
-	}
-#endif
-}
-
-/*
- * Given a media word, return one suitable for an application
- * using the original encoding.
- */
-static int
-compat_media(int media)
+ifmedia_free(struct ifnet *ifp)
 {
+	struct ifmedia *ifm;
 
-	if (IFM_TYPE(media) == IFM_ETHER && IFM_SUBTYPE(media) > IFM_OTHER) {
-		media &= ~(IFM_ETH_XTYPE|IFM_TMASK);
-		media |= IFM_OTHER;
-	}
-	return (media);
+	ifm = if_getsoftc(ifp, IF_MEDIA);
+	if_setsoftc(ifp, IF_MEDIA, NULL);
+	free(ifm, M_IFMEDIA);
 }
 
 /*
  * Device-independent media ioctl support function.
  */
 int
-ifmedia_ioctl(ifp, ifr, ifm, cmd)
-	struct ifnet *ifp;
-	struct ifreq *ifr;
-	struct ifmedia *ifm;
-	u_long cmd;
+ifmedia_ioctl(struct ifnet *ifp, struct ifreq *ifr, u_long cmd)
 {
-	struct ifmedia_entry *match;
 	struct ifmediareq *ifmr = (struct ifmediareq *) ifr;
-	int error = 0;
+	struct ifmedia *ifm;
+	if_media_t newmedia, *match;
+	int i, error;
 
-	if (ifp == NULL || ifr == NULL || ifm == NULL)
-		return(EINVAL);
+	ifm = if_getsoftc(ifp, IF_MEDIA);
+	if (ifm == NULL)
+		return (ENODEV);
 
+	error = 0;
 	switch (cmd) {
-
-	/*
-	 * Set the current media.
-	 */
 	case  SIOCSIFMEDIA:
-	{
-		struct ifmedia_entry *oldentry;
-		int oldmedia;
-		int newmedia = ifr->ifr_media;
-
-		match = ifmedia_match(ifm, newmedia, ifm->ifm_mask);
+		newmedia = ifr->ifr_media;
+		match = ifmedia_match(ifm, newmedia);
 		if (match == NULL) {
 #ifdef IFMEDIA_DEBUG
 			if (ifmedia_debug) {
-				printf(
-				    "ifmedia_ioctl: no media found for 0x%x\n", 
-				    newmedia);
+				printf("%s: no media found for 0x%x\n", 
+				    __func__, newmedia);
 			}
 #endif
 			return (ENXIO);
@@ -252,14 +137,11 @@ ifmedia_ioctl(ifp, ifr, ifm, cmd)
 
 		/*
 		 * If no change, we're done.
-		 * XXX Automedia may invole software intervention.
-		 *     Keep going in case the connected media changed.
-		 *     Similarly, if best match changed (kernel debugger?).
 		 */
 		if ((IFM_SUBTYPE(newmedia) != IFM_AUTO) &&
 		    (newmedia == ifm->ifm_media) &&
 		    (match == ifm->ifm_cur))
-			return 0;
+			return (0);
 
 		/*
 		 * We found a match, now make the driver switch to it.
@@ -268,57 +150,52 @@ ifmedia_ioctl(ifp, ifr, ifm, cmd)
 		 */
 #ifdef IFMEDIA_DEBUG
 		if (ifmedia_debug) {
-			printf("ifmedia_ioctl: switching %s to ",
-			    ifp->if_xname);
-			ifmedia_printword(match->ifm_media);
+			printf("%s: switching %s to ", __func__, ifp->if_xname);
+			ifmedia_printword(*match);
 		}
 #endif
-		oldentry = ifm->ifm_cur;
-		oldmedia = ifm->ifm_media;
+		error = ifp->if_ops->ifop_media_change(ifp, newmedia);
+		if (error)
+			break;
 		ifm->ifm_cur = match;
 		ifm->ifm_media = newmedia;
-		error = (*ifm->ifm_change)(ifp);
-		if (error) {
-			ifm->ifm_cur = oldentry;
-			ifm->ifm_media = oldmedia;
-		}
+		/*
+		 * Some drivers, e.g. miibus(4) enabled, already set the
+		 * baudrate in ifop_media_change, but some may not.
+		 */
+		ifp->if_baudrate = ifmedia_baudrate(newmedia);
+		
 		break;
-	}
 
 	/*
 	 * Get list of available media and current media on interface.
 	 */
 	case  SIOCGIFMEDIA: 
 	case  SIOCGIFXMEDIA: 
-	{
-		struct ifmedia_entry *ep;
-		int i;
-
 		if (ifmr->ifm_count < 0)
 			return (EINVAL);
 
 		if (cmd == SIOCGIFMEDIA) {
 			ifmr->ifm_active = ifmr->ifm_current = ifm->ifm_cur ?
-			    compat_media(ifm->ifm_cur->ifm_media) : IFM_NONE;
+			    ifmedia_compat(*ifm->ifm_cur) : IFM_NONE;
 		} else {
 			ifmr->ifm_active = ifmr->ifm_current = ifm->ifm_cur ?
-			    ifm->ifm_cur->ifm_media : IFM_NONE;
+			    *ifm->ifm_cur : IFM_NONE;
 		}
 		ifmr->ifm_mask = ifm->ifm_mask;
 		ifmr->ifm_status = 0;
-		(*ifm->ifm_status)(ifp, ifmr);
+		ifp->if_ops->ifop_media_status(ifp, ifmr);
 
 		/*
-		 * If there are more interfaces on the list, count
+		 * If there are more supported mediae on the list, count
 		 * them.  This allows the caller to set ifmr->ifm_count
 		 * to 0 on the first call to know how much space to
 		 * allocate.
 		 */
-		i = 0;
-		LIST_FOREACH(ep, &ifm->ifm_list, ifm_list)
-			if (i++ < ifmr->ifm_count) {
-				error = copyout(&ep->ifm_media,
-				    ifmr->ifm_ulist + i - 1, sizeof(int));
+		for (i = 0; ifm->ifm_array[i] != 0; i++)
+			if (i < ifmr->ifm_count) {
+				error = copyout(&ifm->ifm_array[i],
+				    ifmr->ifm_ulist + i, sizeof(if_media_t));
 				if (error)
 					break;
 			}
@@ -326,7 +203,6 @@ ifmedia_ioctl(ifp, ifr, ifm, cmd)
 			error = ifmr->ifm_count ? E2BIG : 0;
 		ifmr->ifm_count = i;
 		break;
-	}
 
 	default:
 		return (EINVAL);
@@ -336,33 +212,71 @@ ifmedia_ioctl(ifp, ifr, ifm, cmd)
 }
 
 /*
- * Find media entry matching a given ifm word.
- *
+ * Upcall from driver to report new media status.
+ * We intentionally don't change ifm_cur or ifm_media, since this
+ * upcall should come only in case if media is set to autonegotiation.
+ */
+void
+if_media_status(struct ifnet *ifp, if_media_t media)
+{
+
+	if_setbaudrate(ifp, ifmedia_baudrate(media));
+	if_link_state_change(ifp, ifmedia_link_state(media));
+}
+
+/*
+ * Interface wants to change its media list.
  */
-static struct ifmedia_entry *
-ifmedia_match(ifm, target, mask)
-	struct ifmedia *ifm; 
-	int target;
-	int mask;
+void
+if_media_change(struct ifnet *ifp, if_media_t *array, if_media_t cur)
 {
-	struct ifmedia_entry *match, *next;
+	struct ifmedia *ifm;
+
+	ifm = if_getsoftc(ifp, IF_MEDIA);
+	ifm->ifm_array = array;
+	ifm->ifm_cur = ifmedia_match(ifm, cur);
+	ifm->ifm_media = *ifm->ifm_cur;
+
+	ifp->if_baudrate = ifmedia_baudrate(ifm->ifm_media);
+}
 
+/*
+ * Find media entry index matching a given ifm word.
+ */
+static if_media_t *
+ifmedia_match(struct ifmedia *ifm, if_media_t target)
+{
+	if_media_t *match, mask;
+
+	mask = ~ifm->ifm_mask;
 	match = NULL;
-	mask = ~mask;
 
-	LIST_FOREACH(next, &ifm->ifm_list, ifm_list) {
-		if ((next->ifm_media & mask) == (target & mask)) {
+	for (int i = 0; ifm->ifm_array[i] != 0; i++)
+		if ((ifm->ifm_array[i] & mask) == (target & mask)) {
 #if defined(IFMEDIA_DEBUG) || defined(DIAGNOSTIC)
-			if (match) {
-				printf("ifmedia_match: multiple match for "
-				    "0x%x/0x%x\n", target, mask);
-			}
+			if (match != NULL)
+				printf("%s: multiple match for "
+				    "0x%x/0x%x\n", __func__, target, mask);
 #endif
-			match = next;
+			match = &ifm->ifm_array[i];
 		}
-	}
 
-	return match;
+	return (match);
+}
+
+/*
+ * Given a media word, return one suitable for an application
+ * using the original encoding.
+ */
+static if_media_t
+ifmedia_compat(if_media_t media)
+{
+
+	if (IFM_TYPE(media) == IFM_ETHER && IFM_SUBTYPE(media) > IFM_OTHER) {
+		media &= ~(IFM_ETH_XTYPE|IFM_TMASK);
+		media |= IFM_OTHER;
+	}
+	return (media);
 }
 
 /*
@@ -372,8 +286,8 @@ ifmedia_match(ifm, target, mask)
 static const struct ifmedia_baudrate ifmedia_baudrate_descriptions[] =   
     IFM_BAUDRATE_DESCRIPTIONS;
 
-uint64_t
-ifmedia_baudrate(int mword)
+static uint64_t
+ifmedia_baudrate(if_media_t mword)
 {
 	int i;
 
@@ -386,7 +300,7 @@ ifmedia_baudrate(int mword)
 	return (0);
 }
 
-int
+static int
 ifmedia_link_state(u_int mstatus)
 {
 
@@ -400,6 +314,9 @@ ifmedia_link_state(u_int mstatus)
 }
  
 #ifdef IFMEDIA_DEBUG
+SYSCTL_INT(_debug, OID_AUTO, ifmedia, CTLFLAG_RW, &ifmedia_debug,
+	    0, "if_media debugging msgs");
+
 struct ifmedia_description ifm_type_descriptions[] =
     IFM_TYPE_DESCRIPTIONS;
 

Modified: projects/ifnet/sys/net/if_media.h
==============================================================================
--- projects/ifnet/sys/net/if_media.h	Sun Apr 26 12:24:42 2015	(r282020)
+++ projects/ifnet/sys/net/if_media.h	Sun Apr 26 15:40:58 2015	(r282021)
@@ -39,83 +39,10 @@
 #define	_NET_IF_MEDIA_H_
 
 /*
- * Prototypes and definitions for BSD/OS-compatible network interface
- * media selection.
+ * Interface media description could be bigger than a 32-bit word,   
+ * but a conservative decision was taken in r281236.
  *
- * Where it is safe to do so, this code strays slightly from the BSD/OS
- * design.  Software which uses the API (device drivers, basically)
- * shouldn't notice any difference.
- *
- * Many thanks to Matt Thomas for providing the information necessary
- * to implement this interface.
- */
-
-#ifdef _KERNEL
-
-#include <sys/queue.h>
-
-struct ifnet;
-
-/*
- * Driver callbacks for media status and change requests.
- */
-typedef	int (*ifm_change_cb_t)(struct ifnet *);
-typedef	void (*ifm_stat_cb_t)(struct ifnet *, struct ifmediareq *req);
-
-/*
- * In-kernel representation of a single supported media type.
- */
-struct ifmedia_entry {
-	LIST_ENTRY(ifmedia_entry) ifm_list;
-	int	ifm_media;	/* description of this media attachment */
-	int	ifm_data;	/* for driver-specific use */
-	void	*ifm_aux;	/* for driver-specific use */
-};
-
-/*
- * One of these goes into a network interface's softc structure.
- * It is used to keep general media state.
- */
-struct ifmedia {
-	int	ifm_mask;	/* mask of changes we don't care about */
-	int	ifm_media;	/* current user-set media word */
-	struct ifmedia_entry *ifm_cur;	/* currently selected media */
-	LIST_HEAD(, ifmedia_entry) ifm_list; /* list of all supported media */
-	ifm_change_cb_t	ifm_change;	/* media change driver callback */
-	ifm_stat_cb_t	ifm_status;	/* media status driver callback */
-};
-
-/* Initialize an interface's struct if_media field. */
-void	ifmedia_init(struct ifmedia *ifm, int dontcare_mask,
-	    ifm_change_cb_t change_callback, ifm_stat_cb_t status_callback);
-
-/* Remove all mediums from a struct ifmedia.  */
-void	ifmedia_removeall( struct ifmedia *ifm);
-
-/* Add one supported medium to a struct ifmedia. */
-void	ifmedia_add(struct ifmedia *ifm, int mword, int data, void *aux);
-
-/* Add an array (of ifmedia_entry) media to a struct ifmedia. */
-void	ifmedia_list_add(struct ifmedia *mp, struct ifmedia_entry *lp,
-	    int count);
-
-/* Set default media type on initialization. */
-void	ifmedia_set(struct ifmedia *ifm, int mword);
-
-/* Common ioctl function for getting/setting media, called by driver. */
-int	ifmedia_ioctl(struct ifnet *ifp, struct ifreq *ifr,
-	    struct ifmedia *ifm, u_long cmd);
-
-/* Compute baudrate for a given media. */
-uint64_t	ifmedia_baudrate(int);
-
-/* Convert media status to link state. */
-int	ifmedia_link_state(u_int);
-
-#endif /*_KERNEL */
-
-/*
- * if_media Options word:
+ * Options word:
  *	Bits	Use
  *	----	-------
  *	0-4	Media variant
@@ -126,6 +53,7 @@ int	ifmedia_link_state(u_int);
  *	20-27	Shared (global) options
  *	28-31	Instance
  */
+typedef int if_media_t;
 
 /*
  * Ethernet



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