Hi Gerhard, Today I added Your patches to 6.7-stable and moved back LTE modem to USB 3.0. So, just waiting for… nothing or kernel panic. I’ll let you know.
> On 8 Jun 2020, at 19:13, Patrick Wildt <patr...@blueri.se> wrote: > > On Mon, Jun 08, 2020 at 05:31:44PM +0200, Gerhard Roth wrote: >> On 2020-05-25 13:19, Martin Pieuchot wrote: >>> On 25/05/20(Mon) 12:56, Gerhard Roth wrote: >>>> On 5/22/20 9:05 PM, Mark Kettenis wrote: >>>>>> From: Łukasz Lejtkowski <emig...@gmail.com> >>>>>> Date: Fri, 22 May 2020 20:51:57 +0200 >>>>>> >>>>>> Probably power supply 12 V is broken. Showing 16,87 V(Fluke 179) - >>>>>> too high. Should be 12,25-12,50 V. I replaced to the new one. >>>>> >>>>> That might be why the device stops responding. The fact that cleaning >>>>> up from a failed USB transaction leads to this panic is a bug though. >>>>> >>>>> And somebody just posted a very similar panic with ure(4). Something >>>>> in the network stack is holding a mutex when it shouldn't. >>>> >>>> I think that holding the mutex is ok. The bug is calling the stop >>>> routine in case of errors. >>>> >>>> This is what common foo_start() does: >>>> >>>> m_head = ifq_deq_begin(&ifp->if_snd); >>>> if (foo_encap(sc, m_head, 0)) { >>>> ifq_deq_rollback(&ifp->if_snd, m_head); >>>> ... >>>> return; >>>> } >>>> ifq_deq_commit(&ifp->if_snd, m_head); >>>> >>>> Here, ifq_deq_begin() grabs a mutex and it is held while >>>> calling foo_encap(). >>>> >>>> For USB network interfaces foo_encap() mostly does this: >>>> >>>> err = usbd_transfer(sc->sc_xfer); >>>> if (err != USBD_IN_PROGRESS) { >>>> foo_stop(sc); >>>> return EIO; >>>> } >>>> >>>> And foo_stop() calls usbd_abort_pipe() -> xhci_command_submit(), >>>> which might sleep. >>>> >>>> How to fix? We could do the foo_encap() after the ifq_deq_commit(), >>>> possibly dropping the current mbuf if encap fails (who cares >>>> for the packets after foo_stop() anyway). >>> >>> That's the approach taken by drivers using ifq_dequeue(9) instead of >>> ifq_deq_begin/commit(). >>> >>>> Or change all the drivers to follow the path that if_aue.c takes: >>>> >>>> err = usbd_transfer(c->aue_xfer); >>>> if (err != USBD_IN_PROGRESS) { >>>> ... >>>> /* Stop the interface from process context. */ >>>> usb_add_task(sc->aue_udev, &sc->aue_stop_task); >>>> return (EIO); >>>> } >>> >>> That's just trading the current problem for another one with higher >>> complexity. >>> >>>> Any ideas, what's better? Or alternative proposals? >>> >>> Using ifq_dequeue(9) would have the advantage of unifying the code base. >>> It introduces a behavior change. A simpler fix would be to call >>> foo_stop() in the error path after ifq_deq_rollback(). >>> >> >> Hi, >> >> two weeks passed any nobody objected Martin's proposal. So I thought, >> we could try to move on this way. >> >> Gerhard >> > > From what I remember from various discussions, the goal should be to > check if there's a buffer free in the ring, then dequeue and send, and > it it can't be sent out, then drop it. With USB apparently those > drivers "always" have an open buffer, so we can just dequeue and send, > like you do in this diff. And if it gets dropped, that's fine. > > That said, I think IFQ_DEQUEUE() is old compat code, and we actually > nowadays prefer: > > m_head = ifq_dequeue(&ifp->if_snd); > > If you look at the define for IFQ_DEQUEUE() you'll see it's marked > as compat code. If you look at a new driver, like ixl(4), you'll > see that it also uses ifq_dequeue(). > > Sorry to to give you some work, but with that fixed: ok patrick@ > > Patrick > >> >> Index: sys/dev/usb/if_axe.c >> =================================================================== >> RCS file: /cvs/src/sys/dev/usb/if_axe.c,v >> retrieving revision 1.139 >> diff -u -p -u -p -r1.139 if_axe.c >> --- sys/dev/usb/if_axe.c 7 Jul 2019 06:40:10 -0000 1.139 >> +++ sys/dev/usb/if_axe.c 8 Jun 2020 15:13:25 -0000 >> @@ -1223,6 +1223,7 @@ axe_encap(struct axe_softc *sc, struct m >> /* Transmit */ >> err = usbd_transfer(c->axe_xfer); >> if (err != USBD_IN_PROGRESS) { >> + c->axe_mbuf = NULL; >> axe_stop(sc); >> return(EIO); >> } >> @@ -1246,16 +1247,15 @@ axe_start(struct ifnet *ifp) >> if (ifq_is_oactive(&ifp->if_snd)) >> return; >> >> - m_head = ifq_deq_begin(&ifp->if_snd); >> + IFQ_DEQUEUE(&ifp->if_snd, m_head); >> if (m_head == NULL) >> return; >> >> if (axe_encap(sc, m_head, 0)) { >> - ifq_deq_rollback(&ifp->if_snd, m_head); >> + m_freem(m_head); >> ifq_set_oactive(&ifp->if_snd); >> return; >> } >> - ifq_deq_commit(&ifp->if_snd, m_head); >> >> /* >> * If there's a BPF listener, bounce a copy of this frame >> Index: sys/dev/usb/if_axen.c >> =================================================================== >> RCS file: /cvs/src/sys/dev/usb/if_axen.c,v >> retrieving revision 1.27 >> diff -u -p -u -p -r1.27 if_axen.c >> --- sys/dev/usb/if_axen.c 7 Jul 2019 06:40:10 -0000 1.27 >> +++ sys/dev/usb/if_axen.c 8 Jun 2020 14:49:26 -0000 >> @@ -1186,6 +1186,7 @@ axen_encap(struct axen_softc *sc, struct >> /* Transmit */ >> err = usbd_transfer(c->axen_xfer); >> if (err != USBD_IN_PROGRESS) { >> + c->axen_mbuf = NULL; >> axen_stop(sc); >> return EIO; >> } >> @@ -1209,16 +1210,15 @@ axen_start(struct ifnet *ifp) >> if (ifq_is_oactive(&ifp->if_snd)) >> return; >> >> - m_head = ifq_deq_begin(&ifp->if_snd); >> + IFQ_DEQUEUE(&ifp->if_snd, m_head); >> if (m_head == NULL) >> return; >> >> if (axen_encap(sc, m_head, 0)) { >> - ifq_deq_rollback(&ifp->if_snd, m_head); >> + m_freem(m_head); >> ifq_set_oactive(&ifp->if_snd); >> return; >> } >> - ifq_deq_commit(&ifp->if_snd, m_head); >> >> /* >> * If there's a BPF listener, bounce a copy of this frame >> Index: sys/dev/usb/if_cdce.c >> =================================================================== >> RCS file: /cvs/src/sys/dev/usb/if_cdce.c,v >> retrieving revision 1.76 >> diff -u -p -u -p -r1.76 if_cdce.c >> --- sys/dev/usb/if_cdce.c 14 Nov 2019 13:50:55 -0000 1.76 >> +++ sys/dev/usb/if_cdce.c 8 Jun 2020 14:50:40 -0000 >> @@ -375,18 +375,16 @@ cdce_start(struct ifnet *ifp) >> if (usbd_is_dying(sc->cdce_udev) || ifq_is_oactive(&ifp->if_snd)) >> return; >> >> - m_head = ifq_deq_begin(&ifp->if_snd); >> + IFQ_DEQUEUE(&ifp->if_snd, m_head); >> if (m_head == NULL) >> return; >> >> if (cdce_encap(sc, m_head, 0)) { >> - ifq_deq_rollback(&ifp->if_snd, m_head); >> + m_freem(m_head); >> ifq_set_oactive(&ifp->if_snd); >> return; >> } >> >> - ifq_deq_commit(&ifp->if_snd, m_head); >> - >> #if NBPFILTER > 0 >> if (ifp->if_bpf) >> bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT); >> @@ -422,6 +420,7 @@ cdce_encap(struct cdce_softc *sc, struct >> 10000, cdce_txeof); >> err = usbd_transfer(c->cdce_xfer); >> if (err != USBD_IN_PROGRESS) { >> + c->cdce_mbuf = NULL; >> cdce_stop(sc); >> return (EIO); >> } >> Index: sys/dev/usb/if_kue.c >> =================================================================== >> RCS file: /cvs/src/sys/dev/usb/if_kue.c,v >> retrieving revision 1.89 >> diff -u -p -u -p -r1.89 if_kue.c >> --- sys/dev/usb/if_kue.c 2 Oct 2018 19:49:10 -0000 1.89 >> +++ sys/dev/usb/if_kue.c 8 Jun 2020 14:52:27 -0000 >> @@ -829,6 +829,7 @@ kue_send(struct kue_softc *sc, struct mb >> if (err != USBD_IN_PROGRESS) { >> printf("%s: kue_send error=%s\n", sc->kue_dev.dv_xname, >> usbd_errstr(err)); >> + c->kue_mbuf = NULL; >> kue_stop(sc); >> return (EIO); >> } >> @@ -852,17 +853,15 @@ kue_start(struct ifnet *ifp) >> if (ifq_is_oactive(&ifp->if_snd)) >> return; >> >> - m_head = ifq_deq_begin(&ifp->if_snd); >> + IFQ_DEQUEUE(&ifp->if_snd, m_head); >> if (m_head == NULL) >> return; >> >> if (kue_send(sc, m_head, 0)) { >> - ifq_deq_rollback(&ifp->if_snd, m_head); >> + m_freem(m_head); >> ifq_set_oactive(&ifp->if_snd); >> return; >> } >> - >> - ifq_deq_commit(&ifp->if_snd, m_head); >> >> #if NBPFILTER > 0 >> /* >> Index: sys/dev/usb/if_mos.c >> =================================================================== >> RCS file: /cvs/src/sys/dev/usb/if_mos.c,v >> retrieving revision 1.40 >> diff -u -p -u -p -r1.40 if_mos.c >> --- sys/dev/usb/if_mos.c 7 Jul 2019 06:40:10 -0000 1.40 >> +++ sys/dev/usb/if_mos.c 8 Jun 2020 15:15:42 -0000 >> @@ -1097,6 +1097,7 @@ mos_encap(struct mos_softc *sc, struct m >> /* Transmit */ >> err = usbd_transfer(c->mos_xfer); >> if (err != USBD_IN_PROGRESS) { >> + c->mos_mbuf = NULL; >> mos_stop(sc); >> return(EIO); >> } >> @@ -1120,16 +1121,15 @@ mos_start(struct ifnet *ifp) >> if (ifq_is_oactive(&ifp->if_snd)) >> return; >> >> - m_head = ifq_deq_begin(&ifp->if_snd); >> + IFQ_DEQUEUE(&ifp->if_snd, m_head); >> if (m_head == NULL) >> return; >> >> if (mos_encap(sc, m_head, 0)) { >> - ifq_deq_rollback(&ifp->if_snd, m_head); >> + m_freem(m_head); >> ifq_set_oactive(&ifp->if_snd); >> return; >> } >> - ifq_deq_commit(&ifp->if_snd, m_head); >> >> /* >> * If there's a BPF listener, bounce a copy of this frame >> Index: sys/dev/usb/if_mue.c >> =================================================================== >> RCS file: /cvs/src/sys/dev/usb/if_mue.c,v >> retrieving revision 1.7 >> diff -u -p -u -p -r1.7 if_mue.c >> --- sys/dev/usb/if_mue.c 7 Jul 2019 06:40:10 -0000 1.7 >> +++ sys/dev/usb/if_mue.c 8 Jun 2020 14:55:07 -0000 >> @@ -987,6 +987,7 @@ mue_encap(struct mue_softc *sc, struct m >> /* Transmit */ >> err = usbd_transfer(c->mue_xfer); >> if (err != USBD_IN_PROGRESS) { >> + c->mue_mbuf = NULL; >> mue_stop(sc); >> return(EIO); >> } >> @@ -1308,16 +1309,15 @@ mue_start(struct ifnet *ifp) >> if (ifq_is_oactive(&ifp->if_snd)) >> return; >> >> - m_head = ifq_deq_begin(&ifp->if_snd); >> + IFQ_DEQUEUE(&ifp->if_snd, m_head); >> if (m_head == NULL) >> return; >> >> if (mue_encap(sc, m_head, 0)) { >> - ifq_deq_rollback(&ifp->if_snd, m_head); >> + m_freem(m_head); >> ifq_set_oactive(&ifp->if_snd); >> return; >> } >> - ifq_deq_commit(&ifp->if_snd, m_head); >> >> /* If there's a BPF listener, bounce a copy of this frame to him. */ >> #if NBPFILTER > 0 >> Index: sys/dev/usb/if_smsc.c >> =================================================================== >> RCS file: /cvs/src/sys/dev/usb/if_smsc.c,v >> retrieving revision 1.34 >> diff -u -p -u -p -r1.34 if_smsc.c >> --- sys/dev/usb/if_smsc.c 8 Apr 2020 09:49:32 -0000 1.34 >> +++ sys/dev/usb/if_smsc.c 8 Jun 2020 15:02:20 -0000 >> @@ -649,16 +649,15 @@ smsc_start(struct ifnet *ifp) >> return; >> } >> >> - m_head = ifq_deq_begin(&ifp->if_snd); >> + IFQ_DEQUEUE(&ifp->if_snd, m_head); >> if (m_head == NULL) >> return; >> >> if (smsc_encap(sc, m_head, 0)) { >> - ifq_deq_rollback(&ifp->if_snd, m_head); >> + m_freem(m_head); >> ifq_set_oactive(&ifp->if_snd); >> return; >> } >> - ifq_deq_commit(&ifp->if_snd, m_head); >> >> #if NBPFILTER > 0 >> if (ifp->if_bpf) >> @@ -1400,6 +1399,7 @@ smsc_encap(struct smsc_softc *sc, struct >> >> err = usbd_transfer(c->sc_xfer); >> if (err != USBD_IN_PROGRESS) { >> + c->sc_mbuf = NULL; >> smsc_stop(sc); >> return (EIO); >> } >> Index: sys/dev/usb/if_ugl.c >> =================================================================== >> RCS file: /cvs/src/sys/dev/usb/if_ugl.c,v >> retrieving revision 1.23 >> diff -u -p -u -p -r1.23 if_ugl.c >> --- sys/dev/usb/if_ugl.c 2 Oct 2018 19:49:10 -0000 1.23 >> +++ sys/dev/usb/if_ugl.c 8 Jun 2020 15:16:09 -0000 >> @@ -566,6 +566,7 @@ ugl_send(struct ugl_softc *sc, struct mb >> if (err != USBD_IN_PROGRESS) { >> printf("%s: ugl_send error=%s\n", sc->sc_dev.dv_xname, >> usbd_errstr(err)); >> + c->ugl_mbuf = NULL; >> ugl_stop(sc); >> return (EIO); >> } >> @@ -589,17 +590,15 @@ ugl_start(struct ifnet *ifp) >> if (ifq_is_oactive(&ifp->if_snd)) >> return; >> >> - m_head = ifq_deq_begin(&ifp->if_snd); >> + IFQ_DEQUEUE(&ifp->if_snd, m_head); >> if (m_head == NULL) >> return; >> >> if (ugl_send(sc, m_head, 0)) { >> - ifq_deq_rollback(&ifp->if_snd, m_head); >> + m_freem(m_head); >> ifq_set_oactive(&ifp->if_snd); >> return; >> } >> - >> - ifq_deq_commit(&ifp->if_snd, m_head); >> >> #if NBPFILTER > 0 >> /* >> Index: sys/dev/usb/if_upl.c >> =================================================================== >> RCS file: /cvs/src/sys/dev/usb/if_upl.c,v >> retrieving revision 1.75 >> diff -u -p -u -p -r1.75 if_upl.c >> --- sys/dev/usb/if_upl.c 2 Oct 2018 19:49:10 -0000 1.75 >> +++ sys/dev/usb/if_upl.c 8 Jun 2020 15:06:43 -0000 >> @@ -546,6 +546,7 @@ upl_send(struct upl_softc *sc, struct mb >> if (err != USBD_IN_PROGRESS) { >> printf("%s: upl_send error=%s\n", sc->sc_dev.dv_xname, >> usbd_errstr(err)); >> + c->upl_mbuf = NULL; >> upl_stop(sc); >> return (EIO); >> } >> @@ -569,17 +570,15 @@ upl_start(struct ifnet *ifp) >> if (ifq_is_oactive(&ifp->if_snd)) >> return; >> >> - m_head = ifq_deq_begin(&ifp->if_snd); >> + IFQ_DEQUEUE(&ifp->if_snd, m_head); >> if (m_head == NULL) >> return; >> >> if (upl_send(sc, m_head, 0)) { >> - ifq_deq_rollback(&ifp->if_snd, m_head); >> + m_freem(m_head); >> ifq_set_oactive(&ifp->if_snd); >> return; >> } >> - >> - ifq_deq_commit(&ifp->if_snd, m_head); >> >> #if NBPFILTER > 0 >> /* >> Index: sys/dev/usb/if_ure.c >> =================================================================== >> RCS file: /cvs/src/sys/dev/usb/if_ure.c,v >> retrieving revision 1.14 >> diff -u -p -u -p -r1.14 if_ure.c >> --- sys/dev/usb/if_ure.c 10 Mar 2020 01:11:30 -0000 1.14 >> +++ sys/dev/usb/if_ure.c 8 Jun 2020 15:12:53 -0000 >> @@ -775,16 +775,15 @@ ure_start(struct ifnet *ifp) >> break; >> } >> >> - m_head = ifq_deq_begin(&ifp->if_snd); >> + IFQ_DEQUEUE(&ifp->if_snd, m_head); >> if (m_head == NULL) >> break; >> >> if (ure_encap(sc, m_head)) { >> - ifq_deq_rollback(&ifp->if_snd, m_head); >> + m_freem(m_head); >> ifq_set_oactive(&ifp->if_snd); >> break; >> } >> - ifq_deq_commit(&ifp->if_snd, m_head); >> >> #if NBPFILTER > 0 >> if (ifp->if_bpf) >> @@ -1933,6 +1932,7 @@ ure_encap(struct ure_softc *sc, struct m >> >> err = usbd_transfer(c->uc_xfer); >> if (err != 0 && err != USBD_IN_PROGRESS) { >> + c->uc_mbuf = NULL; >> ure_stop(sc); >> return (EIO); >> } >> Index: sys/dev/usb/if_urndis.c >> =================================================================== >> RCS file: /cvs/src/sys/dev/usb/if_urndis.c,v >> retrieving revision 1.69 >> diff -u -p -u -p -r1.69 if_urndis.c >> --- sys/dev/usb/if_urndis.c 22 Jan 2019 18:06:05 -0000 1.69 >> +++ sys/dev/usb/if_urndis.c 8 Jun 2020 15:14:57 -0000 >> @@ -804,6 +804,7 @@ urndis_encap(struct urndis_softc *sc, st >> /* Transmit */ >> err = usbd_transfer(c->sc_xfer); >> if (err != USBD_IN_PROGRESS) { >> + c->sc_mbuf = NULL; >> urndis_stop(sc); >> return(EIO); >> } >> @@ -1190,16 +1191,15 @@ urndis_start(struct ifnet *ifp) >> if (usbd_is_dying(sc->sc_udev) || ifq_is_oactive(&ifp->if_snd)) >> return; >> >> - m_head = ifq_deq_begin(&ifp->if_snd); >> + IFQ_DEQUEUE(&ifp->if_snd, m_head); >> if (m_head == NULL) >> return; >> >> if (urndis_encap(sc, m_head, 0)) { >> - ifq_deq_rollback(&ifp->if_snd, m_head); >> + m_freem(m_head); >> ifq_set_oactive(&ifp->if_snd); >> return; >> } >> - ifq_deq_commit(&ifp->if_snd, m_head); >> >> /* >> * If there's a BPF listener, bounce a copy of this frame