Index: sys/dev/oce/oce_if.c =================================================================== --- sys/dev/oce/oce_if.c +++ sys/dev/oce/oce_if.c @@ -142,6 +142,7 @@ 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 @@ 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,20 @@ } } +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 +1230,8 @@ 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 +1256,8 @@ if (num_cqes) oce_arm_cq(sc, cq->cq_id, num_cqes, FALSE); + UNLOCK(&wq->tx_lock); + return 0; } @@ -2089,6 +2110,9 @@ /* 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); Index: sys/dev/oce/oce_queue.c =================================================================== --- sys/dev/oce/oce_queue.c +++ sys/dev/oce/oce_queue.c @@ -969,7 +969,9 @@ 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 @@ 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_arm_cq(sc, cq->cq_id, num_cqes, FALSE); + UNLOCK(&wq->tx_lock); }