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;