On Sat, May 27, 2017 at 20:06 +0200, Sebastien Marie wrote: > On Sat, May 27, 2017 at 07:28:26AM +0200, Sebastien Marie wrote: > > Hi, > > > > I am experiencing often the following panic: > > > > panic: kernel diagnostic assertion "ifq_is_serialized(ifq)" failed: > > ../sys/net/ifq.c, line 394 > > > > while running with GENERIC.MP patched with mikeb@ diff: > > > > if_start(struct ifnet *ifp) > > { > > KASSERT(ifp->if_qstart == if_qstart_compat); > > - if_qstart_compat(&ifp->if_snd); > > + ifq_start(&ifp->if_snd); > > } > > > > mikeb@, I don't reproduce if I backout the local diff. > > it seems bce(4) doesn't like it.
Indeed, a lot of things won't like this since xxx_start may be called directly by the driver. To handle this situation we need to make sure that IFQ_DEQUEUE that is called by these xxx_start routines provides a compatible interface. Please try the diff below. If this solves your issue, I'd like to get it in w/o assertions unless there are objections. --- sys/net/if.c | 3 ++- sys/net/if_var.h | 2 +- sys/net/ifq.c | 26 ++++++++++++++++++++++++++ sys/net/ifq.h | 1 + 4 files changed, 30 insertions(+), 2 deletions(-) diff --git sys/net/if.c sys/net/if.c index 34fd1aa84d7..acea3ae53ea 100644 --- sys/net/if.c +++ sys/net/if.c @@ -623,12 +623,13 @@ if_attach_ifq(struct ifnet *ifp, const struct ifq_ops *newops, void *args) void if_start(struct ifnet *ifp) { KASSERT(ifp->if_qstart == if_qstart_compat); - if_qstart_compat(&ifp->if_snd); + ifq_start(&ifp->if_snd); } + void if_qstart_compat(struct ifqueue *ifq) { struct ifnet *ifp = ifq->ifq_if; int s; diff --git sys/net/if_var.h sys/net/if_var.h index 14e118bcbef..9df7c8f4d80 100644 --- sys/net/if_var.h +++ sys/net/if_var.h @@ -255,11 +255,11 @@ do { \ (err) = ifq_enqueue((ifq), (m)); \ } while (/* CONSTCOND */0) #define IFQ_DEQUEUE(ifq, m) \ do { \ - (m) = ifq_dequeue(ifq); \ + (m) = ifq_dequeue_compat(ifq); \ } while (/* CONSTCOND */0) #define IFQ_PURGE(ifq) \ do { \ (void)ifq_purge(ifq); \ diff --git sys/net/ifq.c sys/net/ifq.c index d37be87f444..0a49567f81d 100644 --- sys/net/ifq.c +++ sys/net/ifq.c @@ -337,10 +337,36 @@ ifq_dequeue(struct ifqueue *ifq) ifq_deq_commit(ifq, m); return (m); } +struct mbuf * +ifq_dequeue_compat(struct ifqueue *ifq) +{ + struct mbuf *m; + void *serializer; + + KERNEL_ASSERT_LOCKED(); + KASSERT(ifq->ifq_serializer == NULL || + ifq->ifq_serializer == curcpu()); + + serializer = ifq->ifq_serializer; + ifq->ifq_serializer = curcpu(); + + m = ifq_deq_begin(ifq); + if (m == NULL) + return (NULL); + + ifq_deq_commit(ifq, m); + + ml_purge(&ifq->ifq_free); + + ifq->ifq_serializer = serializer; + + return (m); +} + unsigned int ifq_purge(struct ifqueue *ifq) { struct mbuf_list ml = MBUF_LIST_INITIALIZER(); unsigned int rv; diff --git sys/net/ifq.h sys/net/ifq.h index 29b89c38b23..3a7fde55ca2 100644 --- sys/net/ifq.h +++ sys/net/ifq.h @@ -380,10 +380,11 @@ void ifq_destroy(struct ifqueue *); int ifq_enqueue(struct ifqueue *, struct mbuf *); struct mbuf *ifq_deq_begin(struct ifqueue *); void ifq_deq_commit(struct ifqueue *, struct mbuf *); void ifq_deq_rollback(struct ifqueue *, struct mbuf *); struct mbuf *ifq_dequeue(struct ifqueue *); +struct mbuf *ifq_dequeue_compat(struct ifqueue *); void ifq_mfreem(struct ifqueue *, struct mbuf *); void ifq_mfreeml(struct ifqueue *, struct mbuf_list *); unsigned int ifq_purge(struct ifqueue *); void *ifq_q_enter(struct ifqueue *, const struct ifq_ops *); void ifq_q_leave(struct ifqueue *, void *); -- 2.13.0