Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/net Run if_link_state_change in softint



details:   https://anonhg.NetBSD.org/src/rev/318930a12d9d
branches:  trunk
changeset: 343570:318930a12d9d
user:      ozaki-r <ozaki-r%NetBSD.org@localhost>
date:      Mon Feb 15 08:08:04 2016 +0000

description:
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.

diffstat:

 sys/net/if.c |  35 ++++++++++++++++++++++++++++++-----
 sys/net/if.h |   4 +++-
 2 files changed, 33 insertions(+), 6 deletions(-)

diffs (110 lines):

diff -r 38490e70444e -r 318930a12d9d sys/net/if.c
--- a/sys/net/if.c      Mon Feb 15 01:11:41 2016 +0000
+++ b/sys/net/if.c      Mon Feb 15 08:08:04 2016 +0000
@@ -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 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 @@
        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_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 @@
 
        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 @@
 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 @@
                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" :
diff -r 38490e70444e -r 318930a12d9d sys/net/if.h
--- a/sys/net/if.h      Mon Feb 15 01:11:41 2016 +0000
+++ b/sys/net/if.h      Mon Feb 15 08:08:04 2016 +0000
@@ -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 @@
        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;
  



Home | Main Index | Thread Index | Old Index