Date: Tue, 15 Jul 2014 10:22:42 +0200 From: Stefano Garzarella <stefanogarzarella@gmail.com> To: Borja Marcos <borjam@sarenet.es> Cc: "freebsd-net@freebsd.org" <freebsd-net@freebsd.org>, freebsd-current <freebsd-current@freebsd.org>, Luigi Rizzo <rizzo@iet.unipi.it>, Xin LI <d@delphij.net> Subject: Re: Fix Emulex "oce" driver in CURRENT Message-ID: <CAO0mX5bmXnQGuEgSYoBxy8bQK5i3B2MG0LBmJ7A178W1B5sqDw@mail.gmail.com> In-Reply-To: <6C8CF68D-68E2-4168-AA0A-6A629D363371@sarenet.es> References: <CA%2BhQ2%2BimE=%2BncZwpHGhWb175mYiAKV78MV=Dfc1GJf=3XYciPQ@mail.gmail.com> <453BA9EC-BB63-4258-8141-847F41315E1E@sarenet.es> <CA%2BhQ2%2BjaP2fuMaCoorLpGu=uWDPgHy3at5UdtLAOXM2d6uoWkg@mail.gmail.com> <6C8CF68D-68E2-4168-AA0A-6A629D363371@sarenet.es>
next in thread | previous in thread | raw e-mail | index | archive | help
Hi, I found other problems in the "oce" driver during some experiments with netmap in emulation mode. In details: - missing locking: - in some functions there are write accesses on the wq struct (tx queue descriptor) without acquire LOCK on the queue, particularly in oce_wq_handler() that is invoked in the interrupt routine. For this reason there may be race conditions. - tx cleanup: - in oce_if_deactivate() the wq queues are drained but some still pending mbufs are not freed. For this reason, I added the oce_tx_clean() that releases any pending mbufs. I also tried experimenting with iperf3 using the same Borja environment and I don't have panic. Can you try this patch? Do you still have the panic? Cheers, Stefano Garzarella diff --git a/sys/dev/oce/oce_if.c b/sys/dev/oce/oce_if.c index af57491..33b35b4 100644 --- a/sys/dev/oce/oce_if.c +++ b/sys/dev/oce/oce_if.c @@ -142,6 +142,7 @@ static int oce_tx(POCE_SOFTC sc, struct mbuf **mpp, int wq_index); static void oce_tx_restart(POCE_SOFTC sc, struct oce_wq *wq); static void oce_tx_complete(struct oce_wq *wq, uint32_t wqe_idx, uint32_t status); +static void oce_tx_clean(POCE_SOFTC sc); static int oce_multiq_transmit(struct ifnet *ifp, struct mbuf *m, struct oce_wq *wq); @@ -585,8 +586,10 @@ oce_multiq_flush(struct ifnet *ifp) int i = 0; for (i = 0; i < sc->nwqs; i++) { + LOCK(&sc->wq[i]->tx_lock); while ((m = buf_ring_dequeue_sc(sc->wq[i]->br)) != NULL) m_freem(m); + UNLOCK(&sc->wq[i]->tx_lock); } if_qflush(ifp); } @@ -1052,6 +1055,19 @@ oce_tx_complete(struct oce_wq *wq, uint32_t wqe_idx, uint32_t status) } } +static void +oce_tx_clean(POCE_SOFTC sc) { + int i = 0; + struct oce_wq *wq; + + for_all_wq_queues(sc, wq, i) { + LOCK(&wq->tx_lock); + while (wq->pkt_desc_tail != wq->pkt_desc_head) { + oce_tx_complete(wq, 0, 0); + } + UNLOCK(&wq->tx_lock); + } +} static void oce_tx_restart(POCE_SOFTC sc, struct oce_wq *wq) @@ -1213,6 +1229,8 @@ oce_wq_handler(void *arg) struct oce_nic_tx_cqe *cqe; int num_cqes = 0; + LOCK(&wq->tx_lock); + bus_dmamap_sync(cq->ring->dma.tag, cq->ring->dma.map, BUS_DMASYNC_POSTWRITE); cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_tx_cqe); @@ -1237,6 +1255,8 @@ oce_wq_handler(void *arg) if (num_cqes) oce_arm_cq(sc, cq->cq_id, num_cqes, FALSE); + UNLOCK(&wq->tx_lock); + return 0; } @@ -2087,6 +2107,9 @@ oce_if_deactivate(POCE_SOFTC sc) /* Delete RX queue in card with flush param */ oce_stop_rx(sc); + /* Flush the mbufs that are still in TX queues */ + oce_tx_clean(sc); + /* Invalidate any pending cq and eq entries*/ for_all_evnt_queues(sc, eq, i) oce_drain_eq(eq); diff --git a/sys/dev/oce/oce_queue.c b/sys/dev/oce/oce_queue.c index 308c16d..161011b 100644 --- a/sys/dev/oce/oce_queue.c +++ b/sys/dev/oce/oce_queue.c @@ -969,7 +969,9 @@ oce_start_rq(struct oce_rq *rq) int oce_start_wq(struct oce_wq *wq) { + LOCK(&wq->tx_lock); /* XXX: maybe not necessary */ oce_arm_cq(wq->parent, wq->cq->cq_id, 0, TRUE); + UNLOCK(&wq->tx_lock); return 0; } @@ -1076,6 +1078,8 @@ oce_drain_wq_cq(struct oce_wq *wq) struct oce_nic_tx_cqe *cqe; int num_cqes = 0; + LOCK(&wq->tx_lock); /* XXX: maybe not necessary */ + bus_dmamap_sync(cq->ring->dma.tag, cq->ring->dma.map, BUS_DMASYNC_POSTWRITE); @@ -1093,6 +1097,7 @@ oce_drain_wq_cq(struct oce_wq *wq) oce_arm_cq(sc, cq->cq_id, num_cqes, FALSE); + UNLOCK(&wq->tx_lock); } 2014-07-07 13:57 GMT+02:00 Borja Marcos <borjam@sarenet.es>: > > On Jul 7, 2014, at 1:23 PM, Luigi Rizzo wrote: > > > On Mon, Jul 7, 2014 at 1:03 PM, Borja Marcos <borjam@sarenet.es> wrote: > > we'll try to investigate, can you tell us more about the environment you > use ? > > (FreeBSD version, card model (PCI id perhaps), iperf3 invocation line, > > interface configuration etc.) > > > > The main differences between 10.0.747.0 and the code in head (after > > our fix) is the use > > of drbr_enqueue/dequeue versus the peek/putback in the transmit routine. > > > > > > Both drivers still have issues when the link flaps because the > > transmit queue is not cleaned > > up properly (unlike what happens in the linux driver and all FreeBSD > > drivers for different > > hardware), so it might well be that you are seeing some side effect of > > that or other > > problem which manifests itself differently depending on the environment. > > > > 'instant panic' by itself does not tell us anything about what could > > be the problem you experience (and we do not see it with either driver). > > The environment details are here: > > https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=183391 > > The way I produce an instant panic is: > > 1) Connect to another machine (cross connect cable) > > 2) iperf3 -s on the other machine > (The other machine is different, it has an "ix" card) > > 3) iperf3 -t 30 -P 4 -c 10.0.0.1 -N > > In less than 30 seconds, panic. > > > > mierda dumped core - see /var/crash/vmcore.0 > > Mon Jul 7 13:06:44 CEST 2014 > > FreeBSD mierda 10.0-STABLE FreeBSD 10.0-STABLE #2: Mon Jul 7 11:41:45 > CEST 2014 root@mierda:/usr/obj/usr/src/sys/GENERIC amd64 > > panic: sbsndptr: sockbuf 0xfffff800a70489b0 and mbuf 0xfffff801a3326e00 > clashing > > GNU gdb 6.1.1 [FreeBSD] > Copyright 2004 Free Software Foundation, Inc. > GDB is free software, covered by the GNU General Public License, and you > are > welcome to change it and/or distribute copies of it under certain > conditions. > Type "show copying" to see the conditions. > There is absolutely no warranty for GDB. Type "show warranty" for details. > This GDB was configured as "amd64-marcel-freebsd"... > > Unread portion of the kernel message buffer: > panic: sbsndptr: sockbuf 0xfffff800a70489b0 and mbuf 0xfffff801a3326e00 > clashing > cpuid = 12 > KDB: stack backtrace: > #0 0xffffffff8092a470 at kdb_backtrace+0x60 > #1 0xffffffff808ef9c5 at panic+0x155 > #2 0xffffffff80962710 at sbdroprecord_locked+0 > #3 0xffffffff80a8ba8c at tcp_output+0xdbc > #4 0xffffffff80a8987f at tcp_do_segment+0x30ff > #5 0xffffffff80a85b34 at tcp_input+0xd04 > #6 0xffffffff80a1af57 at ip_input+0x97 > #7 0xffffffff809ba512 at netisr_dispatch_src+0x62 > #8 0xffffffff809b1ae6 at ether_demux+0x126 > #9 0xffffffff809b278e at ether_nh_input+0x35e > #10 0xffffffff809ba512 at netisr_dispatch_src+0x62 > #11 0xffffffff81c19ab9 at oce_rx+0x3c9 > #12 0xffffffff81c19536 at oce_rq_handler+0xb6 > #13 0xffffffff81c1bb1c at oce_intr+0xdc > #14 0xffffffff80938b35 at taskqueue_run_locked+0xe5 > #15 0xffffffff809395c8 at taskqueue_thread_loop+0xa8 > #16 0xffffffff808c057a at fork_exit+0x9a > #17 0xffffffff80ccb51e at fork_trampoline+0xe > Uptime: 51m20s > > > > > > > > > > > > > > Borja. > > _______________________________________________ > freebsd-current@freebsd.org mailing list > http://lists.freebsd.org/mailman/listinfo/freebsd-current > To unsubscribe, send any mail to "freebsd-current-unsubscribe@freebsd.org" > -- Stefano Garzarella
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAO0mX5bmXnQGuEgSYoBxy8bQK5i3B2MG0LBmJ7A178W1B5sqDw>