Module Name:    src
Committed By:   ozaki-r
Date:           Mon Feb 15 08:08:04 UTC 2016

Modified Files:
        src/sys/net: if.c if.h

Log Message:
Run if_link_state_change in softint

if_link_state_change can execute the network stack that is expected to
not run in hardware interrupt (at least now), however network drivers
may call it in hardware interrupt. Avoid that by introducing a new
softint for if_link_state_change.

The original patch is provided by mlelstv@ and tweaked a bit by me.

Should fix PR kern/50602.


To generate a diff of this commit:
cvs rdiff -u -r1.323 -r1.324 src/sys/net/if.c
cvs rdiff -u -r1.195 -r1.196 src/sys/net/if.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/net/if.c
diff -u src/sys/net/if.c:1.323 src/sys/net/if.c:1.324
--- src/sys/net/if.c:1.323	Tue Feb  9 08:32:12 2016
+++ src/sys/net/if.c	Mon Feb 15 08:08:04 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: if.c,v 1.323 2016/02/09 08:32:12 ozaki-r Exp $	*/
+/*	$NetBSD: if.c,v 1.324 2016/02/15 08:08:04 ozaki-r Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
@@ -90,7 +90,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.323 2016/02/09 08:32:12 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.324 2016/02/15 08:08:04 ozaki-r Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_inet.h"
@@ -200,6 +200,7 @@ static void if_attachdomain1(struct ifne
 static int ifconf(u_long, void *);
 static int if_clone_create(const char *);
 static int if_clone_destroy(const char *);
+static void if_link_state_change_si(void *);
 
 struct if_percpuq {
 	struct ifnet	*ipq_ifp;
@@ -602,6 +603,7 @@ if_initialize(ifnet_t *ifp)
 	ifp->if_broadcastaddr = 0; /* reliably crash if used uninitialized */
 
 	ifp->if_link_state = LINK_STATE_UNKNOWN;
+	ifp->if_old_link_state = LINK_STATE_UNKNOWN;
 
 	ifp->if_capenable = 0;
 	ifp->if_csum_flags_tx = 0;
@@ -627,6 +629,10 @@ if_initialize(ifnet_t *ifp)
 
 	IF_AFDATA_LOCK_INIT(ifp);
 
+	ifp->if_link_si = softint_establish(SOFTINT_NET, if_link_state_change_si, ifp);
+	if (ifp->if_link_si == NULL)
+		panic("%s: softint_establish() failed", __func__);
+
 	if_getindex(ifp);
 }
 
@@ -1045,6 +1051,9 @@ again:
 
 	IF_AFDATA_LOCK_DESTROY(ifp);
 
+	softint_disestablish(ifp->if_link_si);
+	ifp->if_link_si = NULL;
+
 	/*
 	 * remove packets that came from ifp, from software interrupt queues.
 	 */
@@ -1562,8 +1571,6 @@ void
 if_link_state_change(struct ifnet *ifp, int link_state)
 {
 	int s;
-	int old_link_state;
-	struct domain *dp;
 
 	s = splnet();
 	if (ifp->if_link_state == link_state) {
@@ -1571,8 +1578,26 @@ if_link_state_change(struct ifnet *ifp, 
 		return;
 	}
 
-	old_link_state = ifp->if_link_state;
 	ifp->if_link_state = link_state;
+	softint_schedule(ifp->if_link_si);
+
+	splx(s);
+}
+
+
+static void
+if_link_state_change_si(void *arg)
+{
+	struct ifnet *ifp = arg;
+	int s;
+	int link_state, old_link_state;
+	struct domain *dp;
+
+	s = splnet();
+	link_state = ifp->if_link_state;
+	old_link_state = ifp->if_old_link_state;
+	ifp->if_old_link_state = ifp->if_link_state;
+
 #ifdef DEBUG
 	log(LOG_DEBUG, "%s: link state %s (was %s)\n", ifp->if_xname,
 		link_state == LINK_STATE_UP ? "UP" :

Index: src/sys/net/if.h
diff -u src/sys/net/if.h:1.195 src/sys/net/if.h:1.196
--- src/sys/net/if.h:1.195	Tue Feb  9 08:32:12 2016
+++ src/sys/net/if.h	Mon Feb 15 08:08:04 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: if.h,v 1.195 2016/02/09 08:32:12 ozaki-r Exp $	*/
+/*	$NetBSD: if.h,v 1.196 2016/02/15 08:08:04 ozaki-r Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -358,6 +358,8 @@ typedef struct ifnet {
 	struct krwlock	*if_afdata_lock;
 #endif
 	struct if_percpuq	*if_percpuq; /* We should remove it in the future */
+	void	*if_link_si;		/* softint to handle link state changes */
+	int	if_old_link_state;	/* previous link state */
 #endif
 } ifnet_t;
  

Reply via email to