diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2009-06-18 17:48:16 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2009-06-18 17:48:16 +0000 |
commit | 196175d87c8f783c1f872a0e112169b85441bdf4 (patch) | |
tree | 1da18c066802050da09a49a1dfcd32b5f4c069b3 /sys | |
parent | 2bbbc8be3ecd3d1220d153b4705dc150e32114a4 (diff) |
MCLGETI support for vr(4) interfaces. This will make the newer soekris and
Alix boards suck a little bit less because it will be harder to live lock them
with traffic. Diff mostly adapted from sis(4).
OK kettenis@, dlg@, sthen@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/if_vr.c | 117 | ||||
-rw-r--r-- | sys/dev/pci/if_vrreg.h | 6 |
2 files changed, 66 insertions, 57 deletions
diff --git a/sys/dev/pci/if_vr.c b/sys/dev/pci/if_vr.c index c27788742d9..57038d4af7e 100644 --- a/sys/dev/pci/if_vr.c +++ b/sys/dev/pci/if_vr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vr.c,v 1.95 2009/06/04 16:56:20 sthen Exp $ */ +/* $OpenBSD: if_vr.c,v 1.96 2009/06/18 17:48:15 claudio Exp $ */ /* * Copyright (c) 1997, 1998 @@ -136,9 +136,10 @@ void vr_setcfg(struct vr_softc *, int); void vr_iff(struct vr_softc *); void vr_reset(struct vr_softc *); int vr_list_rx_init(struct vr_softc *); +void vr_fill_rx_ring(struct vr_softc *); int vr_list_tx_init(struct vr_softc *); -int vr_alloc_mbuf(struct vr_softc *, struct vr_chain_onefrag *, struct mbuf *); +int vr_alloc_mbuf(struct vr_softc *, struct vr_chain_onefrag *); /* * Supported devices & quirks @@ -664,6 +665,7 @@ vr_attach(struct device *parent, struct device *self, void *aux) /* * Call MI attach routines. */ + m_clsetwms(ifp, MCLBYTES, 2, VR_RX_LIST_CNT - 1); if_attach(ifp); ether_ifattach(ifp); @@ -750,9 +752,6 @@ vr_list_rx_init(struct vr_softc *sc) sc->sc_listmap->dm_segs[0].ds_addr + offsetof(struct vr_list_data, vr_rx_list[i]); - if (vr_alloc_mbuf(sc, &cd->vr_rx_chain[i], NULL)) - return (ENOBUFS); - if (i == (VR_RX_LIST_CNT - 1)) nexti = 0; else @@ -764,11 +763,30 @@ vr_list_rx_init(struct vr_softc *sc) offsetof(struct vr_list_data, vr_rx_list[nexti])); } - cd->vr_rx_head = &cd->vr_rx_chain[0]; + cd->vr_rx_prod = cd->vr_rx_cons = &cd->vr_rx_chain[0]; + cd->vr_rx_cnt = 0; + vr_fill_rx_ring(sc); return (0); } +void +vr_fill_rx_ring(struct vr_softc *sc) +{ + struct vr_chain_data *cd; + struct vr_list_data *ld; + + cd = &sc->vr_cdata; + ld = sc->vr_ldata; + + while (cd->vr_rx_cnt < VR_RX_LIST_CNT) { + if (vr_alloc_mbuf(sc, cd->vr_rx_prod)) + break; + cd->vr_rx_prod = cd->vr_rx_prod->vr_nextdesc; + cd->vr_rx_cnt++; + } +} + /* * A frame has been uploaded: pass the resulting mbuf chain up to * the higher level protocols. @@ -776,7 +794,7 @@ vr_list_rx_init(struct vr_softc *sc) void vr_rxeof(struct vr_softc *sc) { - struct mbuf *m0, *m; + struct mbuf *m; struct ifnet *ifp; struct vr_chain_onefrag *cur_rx; int total_len = 0; @@ -784,20 +802,21 @@ vr_rxeof(struct vr_softc *sc) ifp = &sc->arpcom.ac_if; - for (;;) { - + while(sc->vr_cdata.vr_rx_cnt > 0) { bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap, 0, sc->sc_listmap->dm_mapsize, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - rxstat = letoh32(sc->vr_cdata.vr_rx_head->vr_ptr->vr_status); + rxstat = letoh32(sc->vr_cdata.vr_rx_cons->vr_ptr->vr_status); if (rxstat & VR_RXSTAT_OWN) break; - rxctl = letoh32(sc->vr_cdata.vr_rx_head->vr_ptr->vr_ctl); + rxctl = letoh32(sc->vr_cdata.vr_rx_cons->vr_ptr->vr_ctl); - m0 = NULL; - cur_rx = sc->vr_cdata.vr_rx_head; - sc->vr_cdata.vr_rx_head = cur_rx->vr_nextdesc; + cur_rx = sc->vr_cdata.vr_rx_cons; + m = cur_rx->vr_mbuf; + cur_rx->vr_mbuf = NULL; + sc->vr_cdata.vr_rx_cons = cur_rx->vr_nextdesc; + sc->vr_cdata.vr_rx_cnt--; /* * If an error occurs, update stats, clear the @@ -827,24 +846,13 @@ vr_rxeof(struct vr_softc *sc) printf("\n"); #endif - /* Reinitialize descriptor */ - cur_rx->vr_ptr->vr_status = htole32(VR_RXSTAT); - cur_rx->vr_ptr->vr_data = - htole32(cur_rx->vr_map->dm_segs[0].ds_addr + - sizeof(u_int64_t)); - cur_rx->vr_ptr->vr_ctl = htole32(VR_RXCTL | VR_RXLEN); - bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap, - 0, sc->sc_listmap->dm_mapsize, - BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); + m_freem(m); continue; } /* No errors; receive the packet. */ total_len = VR_RXBYTES(letoh32(cur_rx->vr_ptr->vr_status)); - m = cur_rx->vr_mbuf; - cur_rx->vr_mbuf = NULL; - bus_dmamap_sync(sc->sc_dmat, cur_rx->vr_map, 0, cur_rx->vr_map->dm_mapsize, BUS_DMASYNC_POSTREAD); bus_dmamap_unload(sc->sc_dmat, cur_rx->vr_map); @@ -856,22 +864,23 @@ vr_rxeof(struct vr_softc *sc) */ total_len -= ETHER_CRC_LEN; -#ifndef __STRICT_ALIGNMENT - if (vr_alloc_mbuf(sc, cur_rx, NULL) == 0) { - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = m->m_len = total_len; - } else -#endif - { +#ifdef __STRICT_ALIGNMENT + if (1) { + struct mbuf *m0; m0 = m_devget(mtod(m, caddr_t), total_len, ETHER_ALIGN, ifp, NULL); - vr_alloc_mbuf(sc, cur_rx, m); + m_freem(m); if (m0 == NULL) { ifp->if_ierrors++; continue; } m = m0; - } + } else +#endif + { + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = m->m_len = total_len; + } ifp->if_ipackets++; if (sc->vr_quirks & VR_Q_CSUM && @@ -897,6 +906,8 @@ vr_rxeof(struct vr_softc *sc) ether_input_mbuf(ifp, m); } + vr_fill_rx_ring(sc); + bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap, 0, sc->sc_listmap->dm_mapsize, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); @@ -928,7 +939,7 @@ vr_rxeoc(struct vr_softc *sc) vr_rxeof(sc); - CSR_WRITE_4(sc, VR_RXADDR, sc->vr_cdata.vr_rx_head->vr_paddr); + CSR_WRITE_4(sc, VR_RXADDR, sc->vr_cdata.vr_rx_cons->vr_paddr); VR_SETBIT16(sc, VR_COMMAND, VR_CMD_RX_ON); VR_SETBIT16(sc, VR_COMMAND, VR_CMD_RX_GO); } @@ -1342,7 +1353,7 @@ vr_init(void *xsc) /* * Load the address of the RX list. */ - CSR_WRITE_4(sc, VR_RXADDR, sc->vr_cdata.vr_rx_head->vr_paddr); + CSR_WRITE_4(sc, VR_RXADDR, sc->vr_cdata.vr_rx_cons->vr_paddr); /* Enable receiver and transmitter. */ CSR_WRITE_2(sc, VR_COMMAND, VR_CMD_TX_NOPOLL|VR_CMD_START| @@ -1550,34 +1561,29 @@ vr_shutdown(void *arg) } int -vr_alloc_mbuf(struct vr_softc *sc, struct vr_chain_onefrag *r, struct mbuf *mb) +vr_alloc_mbuf(struct vr_softc *sc, struct vr_chain_onefrag *r) { struct vr_desc *d; struct mbuf *m; - if (mb == NULL) { - MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m == NULL) - return (ENOBUFS); + if (r == NULL) + return (EINVAL); - MCLGET(m, M_DONTWAIT); - if (!(m->m_flags & M_EXT)) { - m_free(m); - return (ENOBUFS); - } - } else { - m = mb; - m->m_data = m->m_ext.ext_buf; + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == NULL) + return (ENOBUFS); + + MCLGETI(m, M_DONTWAIT, &sc->arpcom.ac_if, MCLBYTES); + if (!(m->m_flags & M_EXT)) { + m_free(m); + return (ENOBUFS); } m->m_len = m->m_pkthdr.len = MCLBYTES; - r->vr_mbuf = m; - m_adj(m, sizeof(u_int64_t)); - if (bus_dmamap_load_mbuf(sc->sc_dmat, r->vr_map, r->vr_mbuf, - BUS_DMA_NOWAIT)) { - m_freem(r->vr_mbuf); + if (bus_dmamap_load_mbuf(sc->sc_dmat, r->vr_map, m, BUS_DMA_NOWAIT)) { + m_free(m); return (ENOBUFS); } @@ -1585,6 +1591,7 @@ vr_alloc_mbuf(struct vr_softc *sc, struct vr_chain_onefrag *r, struct mbuf *mb) BUS_DMASYNC_PREREAD); /* Reinitialize the RX descriptor */ + r->vr_mbuf = m; d = r->vr_ptr; d->vr_data = htole32(r->vr_map->dm_segs[0].ds_addr); d->vr_ctl = htole32(VR_RXCTL | VR_RXLEN); diff --git a/sys/dev/pci/if_vrreg.h b/sys/dev/pci/if_vrreg.h index 3b94eb6e8bb..13f41ad9883 100644 --- a/sys/dev/pci/if_vrreg.h +++ b/sys/dev/pci/if_vrreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vrreg.h,v 1.26 2009/05/12 13:30:56 sthen Exp $ */ +/* $OpenBSD: if_vrreg.h,v 1.27 2009/06/18 17:48:15 claudio Exp $ */ /* * Copyright (c) 1997, 1998 @@ -435,7 +435,9 @@ struct vr_chain_data { struct vr_chain_onefrag vr_rx_chain[VR_RX_LIST_CNT]; struct vr_chain vr_tx_chain[VR_TX_LIST_CNT]; - struct vr_chain_onefrag *vr_rx_head; + struct vr_chain_onefrag *vr_rx_cons; + struct vr_chain_onefrag *vr_rx_prod; + int vr_rx_cnt; struct vr_chain *vr_tx_cons; struct vr_chain *vr_tx_prod; |