Replace kernel lock with mutex in ixl(4) media status.
authorbluhm <bluhm@openbsd.org>
Fri, 29 Sep 2023 19:44:47 +0000 (19:44 +0000)
committerbluhm <bluhm@openbsd.org>
Fri, 29 Sep 2023 19:44:47 +0000 (19:44 +0000)
Witness found that sc_atq_mtx mutex is held when kernel lock is
acquired.  This might cause a deadlock.  Protect sc_media_status
and sc_media_active with the link state mutex instead.  Global
fields ifm->ifm_status and ifm->ifm_active are still protected by
kernel lock.

OK tobhe@

sys/dev/pci/if_ixl.c

index 5f42dd5..7faa27c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_ixl.c,v 1.88 2023/07/19 20:22:05 jan Exp $ */
+/*     $OpenBSD: if_ixl.c,v 1.89 2023/09/29 19:44:47 bluhm Exp $ */
 
 /*
  * Copyright (c) 2013-2015, Intel Corporation
@@ -2074,8 +2074,10 @@ ixl_media_status(struct ifnet *ifp, struct ifmediareq *ifm)
 
        KERNEL_ASSERT_LOCKED();
 
+       mtx_enter(&sc->sc_link_state_mtx);
        ifm->ifm_status = sc->sc_media_status;
        ifm->ifm_active = sc->sc_media_active;
+       mtx_leave(&sc->sc_link_state_mtx);
 }
 
 static void
@@ -3482,9 +3484,7 @@ ixl_link_state_update_iaq(struct ixl_softc *sc, void *arg)
                return;
        }
 
-       KERNEL_LOCK();
        link_state = ixl_set_link_status(sc, iaq);
-       KERNEL_UNLOCK();
        mtx_enter(&sc->sc_link_state_mtx);
        if (ifp->if_link_state != link_state) {
                ifp->if_link_state = link_state;
@@ -4468,9 +4468,6 @@ ixl_set_link_status(struct ixl_softc *sc, const struct ixl_aq_desc *iaq)
 {
        const struct ixl_aq_link_status *status;
        const struct ixl_phy_type *itype;
-
-       KERNEL_ASSERT_LOCKED();
-
        uint64_t ifm_active = IFM_ETHER;
        uint64_t ifm_status = IFM_AVALID;
        int link_state = LINK_STATE_DOWN;
@@ -4496,9 +4493,11 @@ ixl_set_link_status(struct ixl_softc *sc, const struct ixl_aq_desc *iaq)
        baudrate = ixl_search_link_speed(status->link_speed);
 
 done:
+       mtx_enter(&sc->sc_link_state_mtx);
        sc->sc_media_active = ifm_active;
        sc->sc_media_status = ifm_status;
        sc->sc_ac.ac_if.if_baudrate = baudrate;
+       mtx_leave(&sc->sc_link_state_mtx);
 
        return (link_state);
 }