Index: if_myx.c =================================================================== RCS file: /cvs/src/sys/dev/pci/if_myx.c,v retrieving revision 1.70 diff -u -p -r1.70 if_myx.c --- if_myx.c 4 Oct 2014 11:42:27 -0000 1.70 +++ if_myx.c 21 Oct 2014 10:20:59 -0000 @@ -218,6 +218,7 @@ void myx_bufs_init(struct myx_buf_list int myx_bufs_empty(struct myx_buf_list *); struct myx_buf * myx_buf_get(struct myx_buf_list *); void myx_buf_put(struct myx_buf_list *, struct myx_buf *); +void myx_buf_push(struct myx_buf_list *, struct myx_buf *); struct myx_buf * myx_buf_fill(struct myx_softc *, int); void myx_rx_zero(struct myx_softc *, int); @@ -1250,16 +1251,12 @@ free_rxbig: while ((mb = myx_buf_get(&sc->sc_rx_buf_list[MYX_RXBIG])) != NULL) { bus_dmamap_sync(sc->sc_dmat, mb->mb_map, 0, mb->mb_map->dm_mapsize, BUS_DMASYNC_POSTREAD); - bus_dmamap_unload(sc->sc_dmat, mb->mb_map); - m_freem(mb->mb_m); myx_buf_free(sc, mb); } free_rxsmall: while ((mb = myx_buf_get(&sc->sc_rx_buf_list[MYX_RXSMALL])) != NULL) { bus_dmamap_sync(sc->sc_dmat, mb->mb_map, 0, mb->mb_map->dm_mapsize, BUS_DMASYNC_POSTREAD); - bus_dmamap_unload(sc->sc_dmat, mb->mb_map); - m_freem(mb->mb_m); myx_buf_free(sc, mb); } free_rxbig_bufs: @@ -1413,16 +1410,12 @@ myx_down(struct myx_softc *sc) while ((mb = myx_buf_get(&sc->sc_rx_buf_list[MYX_RXBIG])) != NULL) { bus_dmamap_sync(sc->sc_dmat, mb->mb_map, 0, mb->mb_map->dm_mapsize, BUS_DMASYNC_POSTREAD); - bus_dmamap_unload(sc->sc_dmat, mb->mb_map); - m_freem(mb->mb_m); myx_buf_free(sc, mb); } while ((mb = myx_buf_get(&sc->sc_rx_buf_list[MYX_RXSMALL])) != NULL) { bus_dmamap_sync(sc->sc_dmat, mb->mb_map, 0, mb->mb_map->dm_mapsize, BUS_DMASYNC_POSTREAD); - bus_dmamap_unload(sc->sc_dmat, mb->mb_map); - m_freem(mb->mb_m); myx_buf_free(sc, mb); } @@ -1435,8 +1428,6 @@ myx_down(struct myx_softc *sc) while ((mb = myx_buf_get(&sc->sc_tx_buf_list)) != NULL) { bus_dmamap_sync(sc->sc_dmat, mb->mb_map, 0, mb->mb_map->dm_mapsize, BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->sc_dmat, mb->mb_map); - m_freem(mb->mb_m); myx_buf_free(sc, mb); } @@ -1761,6 +1752,7 @@ myx_txeof(struct myx_softc *sc, u_int32_ } m = mb->mb_m; + mb->mb_m = NULL; map = mb->mb_map; free += map->dm_nsegs + (map->dm_mapsize < 60 ? 1 : 0); @@ -1814,16 +1806,22 @@ myx_rxeof(struct myx_softc *sc) bus_dmamap_sync(sc->sc_dmat, mb->mb_map, 0, mb->mb_map->dm_mapsize, BUS_DMASYNC_POSTREAD); - bus_dmamap_unload(sc->sc_dmat, mb->mb_map); - m = mb->mb_m; + if ((len <= MHLEN - ETHER_ALIGN) && + (m = m_gethdr(M_NOWAIT, MT_DATA)) != NULL) + memcpy(m->m_data, mb->mb_m->m_data, len + ETHER_ALIGN); + else { + m = mb->mb_m; + mb->mb_m = NULL; + bus_dmamap_unload(sc->sc_dmat, mb->mb_map); + } + m->m_data += ETHER_ALIGN; m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = m->m_len = len; ml_enqueue(&ml, m); - - myx_buf_put(&sc->sc_rx_buf_free[ring], mb); + myx_buf_push(&sc->sc_rx_buf_free[ring], mb); rxfree[ring]++; } @@ -1946,29 +1944,34 @@ myx_buf_fill(struct myx_softc *sc, int r struct mbuf *m; int rv; - m = MCLGETI(NULL, M_DONTWAIT, NULL, sizes[ring]); - if (m == NULL) - return (NULL); - m->m_len = m->m_pkthdr.len = sizes[ring]; - mb = myx_buf_get(&sc->sc_rx_buf_free[ring]); if (mb == NULL) - goto mfree; + return (NULL); - rv = bus_dmamap_load_mbuf(sc->sc_dmat, mb->mb_map, m, BUS_DMA_NOWAIT); - if (rv != 0) - goto put; + m = mb->mb_m; + if (m == NULL) { + m = MCLGETI(NULL, M_DONTWAIT, NULL, sizes[ring]); + if (m == NULL) + goto put; + m->m_len = m->m_pkthdr.len = sizes[ring]; + + rv = bus_dmamap_load_mbuf(sc->sc_dmat, mb->mb_map, m, + BUS_DMA_NOWAIT); + if (rv != 0) + goto mfree; + + mb->mb_m = m; + } - mb->mb_m = m; bus_dmamap_sync(sc->sc_dmat, mb->mb_map, 0, mb->mb_map->dm_mapsize, BUS_DMASYNC_PREREAD); return (mb); -put: - myx_buf_put(&sc->sc_rx_buf_free[ring], mb); mfree: m_freem(m); +put: + myx_buf_put(&sc->sc_rx_buf_free[ring], mb); return (NULL); } @@ -1979,7 +1982,7 @@ myx_buf_alloc(struct myx_softc *sc, bus_ { struct myx_buf *mb; - mb = pool_get(myx_buf_pool, PR_WAITOK); + mb = pool_get(myx_buf_pool, PR_WAITOK | PR_ZERO); if (mb == NULL) return (NULL); @@ -1995,6 +1998,14 @@ myx_buf_alloc(struct myx_softc *sc, bus_ void myx_buf_free(struct myx_softc *sc, struct myx_buf *mb) { + struct mbuf *m; + + m = mb->mb_m; + if (m != NULL) { + bus_dmamap_unload(sc->sc_dmat, mb->mb_map); + m_freem(m); + } + bus_dmamap_destroy(sc->sc_dmat, mb->mb_map); pool_put(myx_buf_pool, mb); } @@ -2030,6 +2041,14 @@ myx_buf_put(struct myx_buf_list *mbl, st { mtx_enter(&mbl->mbl_mtx); SIMPLEQ_INSERT_TAIL(&mbl->mbl_q, mb, mb_entry); + mtx_leave(&mbl->mbl_mtx); +} + +void +myx_buf_push(struct myx_buf_list *mbl, struct myx_buf *mb) +{ + mtx_enter(&mbl->mbl_mtx); + SIMPLEQ_INSERT_HEAD(&mbl->mbl_q, mb, mb_entry); mtx_leave(&mbl->mbl_mtx); }