On 13/06/2013 5:29, Masanobu SAITOH wrote:
in6_createmkludge() does:

        mk = malloc(sizeof(*mk), M_IPMADDR, M_ZERO|M_WAITOK);

in6_createmkludge() must not be called under interrupt context.

Indeed.
The attached patch should fix this.

Let me know!

Thanks

Roy
Index: sys/dev/mii/mii_physubr.c
===================================================================
RCS file: /cvsroot/src/sys/dev/mii/mii_physubr.c,v
retrieving revision 1.78
diff -u -p -r1.78 mii_physubr.c
--- sys/dev/mii/mii_physubr.c	9 Jun 2013 09:56:17 -0000	1.78
+++ sys/dev/mii/mii_physubr.c	13 Jun 2013 11:17:24 -0000
@@ -436,9 +436,7 @@ mii_phy_statusmsg(struct mii_softc *sc)
 {
 	struct mii_data *mii = sc->mii_pdata;
 	struct ifnet *ifp = mii->mii_ifp;
-	int s;
 
-	s = splnet();
 	if (mii->mii_media_status & IFM_AVALID) {
 		if (mii->mii_media_status & IFM_ACTIVE)
 			if_link_state_change(ifp, LINK_STATE_UP);
@@ -446,7 +444,6 @@ mii_phy_statusmsg(struct mii_softc *sc)
 			if_link_state_change(ifp, LINK_STATE_DOWN);
 	} else
 		if_link_state_change(ifp, LINK_STATE_UNKNOWN);
-	splx(s);
 
 	ifp->if_baudrate = ifmedia_baudrate(mii->mii_media_active);
 }
Index: sys/net/if.c
===================================================================
RCS file: /cvsroot/src/sys/net/if.c,v
retrieving revision 1.263
diff -u -p -r1.263 if.c
--- sys/net/if.c	11 Jun 2013 12:08:29 -0000	1.263
+++ sys/net/if.c	13 Jun 2013 11:17:25 -0000
@@ -1337,10 +1337,13 @@ link_rtrequest(int cmd, struct rtentry *
 void
 if_link_state_change(struct ifnet *ifp, int link_state)
 {
-	int old_link_state;
+	int old_link_state, s;
 
-	if (ifp->if_link_state == link_state)
+	s = splnet();
+	if (ifp->if_link_state == link_state) {
+		splx(s);
 		return;
+	}
 
 	old_link_state = ifp->if_link_state;
 	ifp->if_link_state = link_state;
@@ -1366,7 +1369,7 @@ if_link_state_change(struct ifnet *ifp, 
 	 */
 	if (link_state == LINK_STATE_UP &&
 	    old_link_state == LINK_STATE_UNKNOWN)
-		in6_if_down(ifp);
+		in6_if_link_down(ifp);
 #endif
 
 	/* Notify that the link state has changed. */
@@ -1379,10 +1382,12 @@ if_link_state_change(struct ifnet *ifp, 
 
 #ifdef INET6
 	if (link_state == LINK_STATE_DOWN)
-		in6_if_down(ifp);
+		in6_if_link_down(ifp);
 	else if (link_state == LINK_STATE_UP)
-		in6_if_up(ifp);
+		in6_if_link_up(ifp);
 #endif
+
+	splx(s);
 }
 
 /*
Index: sys/netinet6/in6.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/in6.c,v
retrieving revision 1.164
diff -u -p -r1.164 in6.c
--- sys/netinet6/in6.c	11 Jun 2013 12:08:29 -0000	1.164
+++ sys/netinet6/in6.c	13 Jun 2013 11:17:25 -0000
@@ -2165,7 +2165,7 @@ in6_ifawithifp(struct ifnet *ifp, struct
  * perform DAD when interface becomes IFF_UP.
  */
 void
-in6_if_up(struct ifnet *ifp)
+in6_if_link_up(struct ifnet *ifp)
 {
 	struct ifaddr *ifa;
 	struct in6_ifaddr *ia;
@@ -2206,20 +2206,27 @@ in6_if_up(struct ifnet *ifp)
 		}
 	}
 
+	/* Restore any detached prefixes */
+	pfxlist_onlink_check();
+}
+
+void
+in6_if_up(struct ifnet *ifp)
+{
+
 	/*
 	 * special cases, like 6to4, are handled in in6_ifattach
 	 */
 	in6_ifattach(ifp, NULL);
 
-	/* Restore any detached prefixes */
-	pfxlist_onlink_check();
+	/* interface may not support link state, so bring it up also */
+	in6_if_link_up(ifp);
 }
-
 /*
  * Mark all addresses as detached.
  */
 void
-in6_if_down(struct ifnet *ifp)
+in6_if_link_down(struct ifnet *ifp)
 {
 	struct ifaddr *ifa;
 	struct in6_ifaddr *ia;
@@ -2254,6 +2261,13 @@ in6_if_down(struct ifnet *ifp)
 	pfxlist_onlink_check();
 }
 
+void
+in6_if_down(struct ifnet *ifp)
+{
+
+	in6_if_link_down(ifp);
+}
+
 int
 in6if_do_dad(struct ifnet *ifp)
 {
Index: sys/netinet6/in6.h
===================================================================
RCS file: /cvsroot/src/sys/netinet6/in6.h,v
retrieving revision 1.72
diff -u -p -r1.72 in6.h
--- sys/netinet6/in6.h	11 Jun 2013 12:08:29 -0000	1.72
+++ sys/netinet6/in6.h	13 Jun 2013 11:17:26 -0000
@@ -700,6 +700,8 @@ void	in6_delayed_cksum(struct mbuf *);
 int	in6_localaddr(const struct in6_addr *);
 int	in6_addrscope(const struct in6_addr *);
 struct	in6_ifaddr *in6_ifawithifp(struct ifnet *, struct in6_addr *);
+extern void in6_if_link_up(struct ifnet *);
+extern void in6_if_link_down(struct ifnet *);
 extern void in6_if_up(struct ifnet *);
 extern void in6_if_down(struct ifnet *);
 #ifndef __FreeBSD__

Reply via email to