aboutsummaryrefslogtreecommitdiff
path: root/sys/net/if_lagg.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net/if_lagg.c')
-rw-r--r--sys/net/if_lagg.c57
1 files changed, 35 insertions, 22 deletions
diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c
index 554d8c2c1bcb..bb882ac819ad 100644
--- a/sys/net/if_lagg.c
+++ b/sys/net/if_lagg.c
@@ -137,6 +137,7 @@ static void lagg_port_ifdetach(void *arg __unused, struct ifnet *);
static int lagg_port_checkstacking(struct lagg_softc *);
#endif
static void lagg_port2req(struct lagg_port *, struct lagg_reqport *);
+static void lagg_if_updown(struct lagg_softc *, bool);
static void lagg_init(void *);
static void lagg_stop(struct lagg_softc *);
static int lagg_ioctl(struct ifnet *, u_long, caddr_t);
@@ -1014,7 +1015,6 @@ lagg_port_destroy(struct lagg_port *lp, int rundelport)
static int
lagg_port_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
- struct epoch_tracker et;
struct lagg_reqport *rp = (struct lagg_reqport *)data;
struct lagg_softc *sc;
struct lagg_port *lp = NULL;
@@ -1039,17 +1039,13 @@ lagg_port_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
break;
}
- NET_EPOCH_ENTER(et);
- if ((lp = ifp->if_lagg) == NULL || lp->lp_softc != sc) {
- error = ENOENT;
- NET_EPOCH_EXIT(et);
- break;
- }
-
LAGG_SLOCK(sc);
- lagg_port2req(lp, rp);
+ if (__predict_true((lp = ifp->if_lagg) != NULL &&
+ lp->lp_softc == sc))
+ lagg_port2req(lp, rp);
+ else
+ error = ENOENT; /* XXXGL: can happen? */
LAGG_SUNLOCK(sc);
- NET_EPOCH_EXIT(et);
break;
case SIOCSIFCAP:
@@ -1266,6 +1262,25 @@ lagg_watchdog_infiniband(void *arg)
}
static void
+lagg_if_updown(struct lagg_softc *sc, bool up)
+{
+ struct ifreq ifr = {};
+ struct lagg_port *lp;
+
+ LAGG_XLOCK_ASSERT(sc);
+
+ CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) {
+ if (up)
+ if_up(lp->lp_ifp);
+ else
+ if_down(lp->lp_ifp);
+
+ if (lp->lp_ioctl != NULL)
+ lp->lp_ioctl(lp->lp_ifp, SIOCSIFFLAGS, (caddr_t)&ifr);
+ }
+}
+
+static void
lagg_init(void *xsc)
{
struct lagg_softc *sc = (struct lagg_softc *)xsc;
@@ -1291,6 +1306,8 @@ lagg_init(void *xsc)
if_setlladdr(lp->lp_ifp, IF_LLADDR(ifp), ifp->if_addrlen);
}
+ lagg_if_updown(sc, true);
+
lagg_proto_init(sc);
if (ifp->if_type == IFT_INFINIBAND) {
@@ -1320,13 +1337,14 @@ lagg_stop(struct lagg_softc *sc)
callout_stop(&sc->sc_watchdog);
mtx_unlock(&sc->sc_mtx);
+ lagg_if_updown(sc, false);
+
callout_drain(&sc->sc_watchdog);
}
static int
lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
- struct epoch_tracker et;
struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc;
struct lagg_reqall *ra = (struct lagg_reqall *)data;
struct lagg_reqopts *ro = (struct lagg_reqopts *)data;
@@ -1576,21 +1594,16 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
break;
}
- NET_EPOCH_ENTER(et);
- if ((lp = (struct lagg_port *)tpif->if_lagg) == NULL ||
- lp->lp_softc != sc) {
- error = ENOENT;
- NET_EPOCH_EXIT(et);
- if_rele(tpif);
- break;
- }
-
LAGG_SLOCK(sc);
- lagg_port2req(lp, rp);
+ if (__predict_true((lp = tpif->if_lagg) != NULL &&
+ lp->lp_softc == sc))
+ lagg_port2req(lp, rp);
+ else
+ error = ENOENT; /* XXXGL: can happen? */
LAGG_SUNLOCK(sc);
- NET_EPOCH_EXIT(et);
if_rele(tpif);
break;
+
case SIOCSLAGGPORT:
error = priv_check(td, PRIV_NET_LAGG);
if (error)