diff --git a/sys/dev/mge/if_mge.c b/sys/dev/mge/if_mge.c index 860e3734be2..d479aa24372 100644 --- a/sys/dev/mge/if_mge.c +++ b/sys/dev/mge/if_mge.c @@ -1140,6 +1140,8 @@ mge_intr_rx_locked(struct mge_softc *sc, int count) mb->m_pkthdr.len -= 2; mb->m_data += 2; + mb->m_pkthdr.rcvif = ifp; + mge_offload_process_frame(ifp, mb, status, bufsize); @@ -1159,6 +1161,8 @@ mge_intr_rx_locked(struct mge_softc *sc, int count) count -= 1; } + ifp->if_ipackets += rx_npkts; + return (rx_npkts); } @@ -1437,12 +1441,6 @@ mge_encap(struct mge_softc *sc, struct mbuf *m0) ifp = sc->ifp; - /* Check for free descriptors */ - if (sc->tx_desc_used_count + 1 >= MGE_TX_DESC_NUM) { - /* No free descriptors */ - return (-1); - } - /* Fetch unused map */ desc_no = sc->tx_desc_curr; dw = &sc->mge_tx_desc[desc_no]; @@ -1451,9 +1449,16 @@ mge_encap(struct mge_softc *sc, struct mbuf *m0) /* Create mapping in DMA memory */ error = bus_dmamap_load_mbuf_sg(sc->mge_tx_dtag, mapp, m0, segs, &nsegs, BUS_DMA_NOWAIT); - if (error != 0 || nsegs != 1 ) { + if (error != 0) { + m_freem(m0); + return (error); + } + + /* Only one segment is supported. */ + if (nsegs != 1) { bus_dmamap_unload(sc->mge_tx_dtag, mapp); - return ((error != 0) ? error : -1); + m_freem(m0); + return (-1); } bus_dmamap_sync(sc->mge_tx_dtag, mapp, BUS_DMASYNC_PREWRITE); @@ -1553,15 +1558,33 @@ mge_start_locked(struct ifnet *ifp) if (m0 == NULL) break; - mtmp = m_defrag(m0, M_NOWAIT); - if (mtmp) - m0 = mtmp; + if (m0->m_pkthdr.csum_flags & (CSUM_IP|CSUM_TCP|CSUM_UDP) || + m0->m_flags & M_VLANTAG) { + if (M_WRITABLE(m0) == 0) { + mtmp = m_dup(m0, M_NOWAIT); + m_freem(m0); + if (mtmp == NULL) + continue; + m0 = mtmp; + } + } + /* The driver support only one DMA fragment. */ + if (m0->m_next != NULL) { + mtmp = m_defrag(m0, M_NOWAIT); + if (mtmp) + m0 = mtmp; + } - if (mge_encap(sc, m0)) { + /* Check for free descriptors */ + if (sc->tx_desc_used_count + 1 >= MGE_TX_DESC_NUM) { IF_PREPEND(&ifp->if_snd, m0); ifp->if_drv_flags |= IFF_DRV_OACTIVE; break; } + + if (mge_encap(sc, m0) != 0) + break; + queued++; BPF_MTAP(ifp, m0); }