From 092a17837209dfcdd3306fca96cfa173f717b8de Mon Sep 17 00:00:00 2001 From: "George V. Neville-Neil" Date: Tue, 22 Apr 2014 20:19:09 +0000 Subject: [PATCH] Check that port is started when MAC filter is set The MAC filter set may be called without softc_lock held in the case of SIOCADDMULTI and SIOCDELMULTI ioctls. The ioctl handler checks IFF_DRV_RUNNING flag which implies port started, but it is not guaranteed to remain. softc_lock shared lock can't be held in the case of these ioctls processing, since it results in failure where kernel complains that non-sleepable lock is held in sleeping thread. Both problems are repeatable on LAG with LACP proto bring up. Submitted by: Andrew Rybchenko Sponsored by: Solarflare Communications, Inc. MFC after: 2 weeks --- sys/dev/sfxge/sfxge_port.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/sys/dev/sfxge/sfxge_port.c b/sys/dev/sfxge/sfxge_port.c index 2c7f7728b88..abd2924f2cd 100644 --- a/sys/dev/sfxge/sfxge_port.c +++ b/sys/dev/sfxge/sfxge_port.c @@ -320,10 +320,21 @@ sfxge_mac_filter_set(struct sfxge_softc *sc) struct sfxge_port *port = &sc->port; int rc; - KASSERT(port->init_state == SFXGE_PORT_STARTED, ("port not started")); - mtx_lock(&port->lock); - rc = sfxge_mac_filter_set_locked(sc); + /* + * The function may be called without softc_lock held in the + * case of SIOCADDMULTI and SIOCDELMULTI ioctls. ioctl handler + * checks IFF_DRV_RUNNING flag which implies port started, but + * it is not guaranteed to remain. softc_lock shared lock can't + * be held in the case of these ioctls processing, since it + * results in failure where kernel complains that non-sleepable + * lock is held in sleeping thread. Both problems are repeatable + * on LAG with LACP proto bring up. + */ + if (port->init_state == SFXGE_PORT_STARTED) + rc = sfxge_mac_filter_set_locked(sc); + else + rc = 0; mtx_unlock(&port->lock); return rc; }