From c59556ee285549543577a7ff5deec6247f634afc Mon Sep 17 00:00:00 2001 From: dlg Date: Wed, 20 Aug 2014 00:50:45 +0000 Subject: [PATCH] replace sks jumbo allocator with MCLGETI. the system provides jumbos in the right shape now, we dont have to do it by hand all over the place any more. rework the rxr ring management to use if_rxring while here. largely based on if_sk.c r1.152 and if_skvar.h r1.4 by kettenis. tested by me on: skc0 at pci3 dev 11 function 0 "Schneider & Koch SK-98xx" rev 0x12, GEnesis (0x0): apic 3 int 5 sk0 at skc0 port A: address 00:00:5a:99:8a:ec xmphy0 at sk0 phy 0: XMAC II Gigabit PHY, rev. 2 and this from ian mcwilliam skc0 at pci0 dev 9 function 0 "D-Link DGE-530T B1" rev 0x11, Yukon Lite (0x9): apic 2 int 17 sk0 at skc0 port A: address 00:17:9a:ba:b5:39 eephy0 at sk0 phy 0: 88E1011 Gigabit PHY, rev. 5 tested by brad@ too --- sys/dev/pci/if_sk.c | 338 ++++++++++++----------------------------- sys/dev/pci/if_skvar.h | 18 +-- 2 files changed, 102 insertions(+), 254 deletions(-) diff --git a/sys/dev/pci/if_sk.c b/sys/dev/pci/if_sk.c index 2b499683e0d..896ca6cc4c3 100644 --- a/sys/dev/pci/if_sk.c +++ b/sys/dev/pci/if_sk.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_sk.c,v 1.170 2014/07/22 13:12:11 mpi Exp $ */ +/* $OpenBSD: if_sk.c,v 1.171 2014/08/20 00:50:45 dlg Exp $ */ /* * Copyright (c) 1997, 1998, 1999, 2000 @@ -153,12 +153,10 @@ void sk_watchdog(struct ifnet *); int sk_ifmedia_upd(struct ifnet *); void sk_ifmedia_sts(struct ifnet *, struct ifmediareq *); void skc_reset(struct sk_softc *); -int sk_newbuf(struct sk_if_softc *, int, struct mbuf *, bus_dmamap_t); -int sk_alloc_jumbo_mem(struct sk_if_softc *); -void *sk_jalloc(struct sk_if_softc *); -void sk_jfree(caddr_t, u_int, void *); +int sk_newbuf(struct sk_if_softc *); int sk_reset(struct sk_if_softc *); int sk_init_rx_ring(struct sk_if_softc *); +void sk_fill_rx_ring(struct sk_if_softc *); int sk_init_tx_ring(struct sk_if_softc *); int sk_xmac_miibus_readreg(struct device *, int, int); @@ -547,21 +545,29 @@ sk_init_rx_ring(struct sk_if_softc *sc_if) rd->sk_rx_ring[i].sk_next = htole32(SK_RX_RING_ADDR(sc_if, nexti)); } - for (i = 0; i < SK_RX_RING_CNT; i++) { - if (sk_newbuf(sc_if, i, NULL, - sc_if->sk_cdata.sk_rx_jumbo_map) == ENOBUFS) { - printf("%s: failed alloc of %dth mbuf\n", - sc_if->sk_dev.dv_xname, i); - return (ENOBUFS); - } - } - sc_if->sk_cdata.sk_rx_prod = 0; sc_if->sk_cdata.sk_rx_cons = 0; + if_rxr_init(&sc_if->sk_cdata.sk_rx_ring, 2, SK_RX_RING_CNT); + + sk_fill_rx_ring(sc_if); + return (0); } +void +sk_fill_rx_ring(struct sk_if_softc *sc_if) +{ + struct if_rxring *rxr = &sc_if->sk_cdata.sk_rx_ring; + u_int slots; + + for (slots = if_rxr_get(rxr, SK_RX_RING_CNT); slots > 0; slots--) { + if (sk_newbuf(sc_if) == ENOBUFS) + break; + } + if_rxr_put(rxr, slots); +} + int sk_init_tx_ring(struct sk_if_softc *sc_if) { @@ -609,199 +615,49 @@ sk_init_tx_ring(struct sk_if_softc *sc_if) } int -sk_newbuf(struct sk_if_softc *sc_if, int i, struct mbuf *m, - bus_dmamap_t dmamap) +sk_newbuf(struct sk_if_softc *sc_if) { - struct mbuf *m_new = NULL; + struct mbuf *m; struct sk_chain *c; struct sk_rx_desc *r; + bus_dmamap_t dmamap; + u_int prod; + int error; - if (m == NULL) { - caddr_t buf = NULL; - - MGETHDR(m_new, M_DONTWAIT, MT_DATA); - if (m_new == NULL) - return (ENOBUFS); - - /* Allocate the jumbo buffer */ - buf = sk_jalloc(sc_if); - if (buf == NULL) { - m_freem(m_new); - DPRINTFN(1, ("%s jumbo allocation failed -- packet " - "dropped!\n", sc_if->arpcom.ac_if.if_xname)); - return (ENOBUFS); - } - - /* Attach the buffer to the mbuf */ - m_new->m_len = m_new->m_pkthdr.len = SK_JLEN; - MEXTADD(m_new, buf, SK_JLEN, 0, sk_jfree, sc_if); - } else { - /* - * We're re-using a previously allocated mbuf; - * be sure to re-init pointers and lengths to - * default values. - */ - m_new = m; - m_new->m_len = m_new->m_pkthdr.len = SK_JLEN; - m_new->m_data = m_new->m_ext.ext_buf; - } - m_adj(m_new, ETHER_ALIGN); - - c = &sc_if->sk_cdata.sk_rx_chain[i]; - r = c->sk_desc; - c->sk_mbuf = m_new; - r->sk_data_lo = htole32(dmamap->dm_segs[0].ds_addr + - (((vaddr_t)m_new->m_data - - (vaddr_t)sc_if->sk_cdata.sk_jumbo_buf))); - r->sk_ctl = htole32(SK_JLEN | SK_RXSTAT); - - SK_CDRXSYNC(sc_if, i, BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD); - - return (0); -} - -/* - * Memory management for jumbo frames. - */ - -int -sk_alloc_jumbo_mem(struct sk_if_softc *sc_if) -{ - struct sk_softc *sc = sc_if->sk_softc; - caddr_t ptr, kva; - bus_dma_segment_t seg; - int i, rseg, state, error; - struct sk_jpool_entry *entry; - - state = error = 0; - - /* Grab a big chunk o' storage. */ - if (bus_dmamem_alloc(sc->sc_dmatag, SK_JMEM, PAGE_SIZE, 0, - &seg, 1, &rseg, BUS_DMA_NOWAIT)) { - printf(": can't alloc rx buffers"); + m = MCLGETI(NULL, M_DONTWAIT, NULL, SK_JLEN); + if (m == NULL) return (ENOBUFS); - } - - state = 1; - if (bus_dmamem_map(sc->sc_dmatag, &seg, rseg, SK_JMEM, &kva, - BUS_DMA_NOWAIT)) { - printf(": can't map dma buffers (%d bytes)", SK_JMEM); - error = ENOBUFS; - goto out; - } - - state = 2; - if (bus_dmamap_create(sc->sc_dmatag, SK_JMEM, 1, SK_JMEM, 0, - BUS_DMA_NOWAIT, &sc_if->sk_cdata.sk_rx_jumbo_map)) { - printf(": can't create dma map"); - error = ENOBUFS; - goto out; - } - - state = 3; - if (bus_dmamap_load(sc->sc_dmatag, sc_if->sk_cdata.sk_rx_jumbo_map, - kva, SK_JMEM, NULL, BUS_DMA_NOWAIT)) { - printf(": can't load dma map"); - error = ENOBUFS; - goto out; - } - state = 4; - sc_if->sk_cdata.sk_jumbo_buf = (caddr_t)kva; - DPRINTFN(1,("sk_jumbo_buf = 0x%08X\n", sc_if->sk_cdata.sk_jumbo_buf)); + m->m_len = m->m_pkthdr.len = SK_JLEN; + m_adj(m, ETHER_ALIGN); - LIST_INIT(&sc_if->sk_jfree_listhead); - LIST_INIT(&sc_if->sk_jinuse_listhead); + prod = sc_if->sk_cdata.sk_rx_prod; + dmamap = sc_if->sk_cdata.sk_rx_map[prod]; - /* - * Now divide it up into 9K pieces and save the addresses - * in an array. - */ - ptr = sc_if->sk_cdata.sk_jumbo_buf; - for (i = 0; i < SK_JSLOTS; i++) { - sc_if->sk_cdata.sk_jslots[i] = ptr; - ptr += SK_JLEN; - entry = malloc(sizeof(struct sk_jpool_entry), - M_DEVBUF, M_NOWAIT); - if (entry == NULL) { - sc_if->sk_cdata.sk_jumbo_buf = NULL; - printf(": no memory for jumbo buffer queue!"); - error = ENOBUFS; - goto out; - } - entry->slot = i; - LIST_INSERT_HEAD(&sc_if->sk_jfree_listhead, - entry, jpool_entries); - } -out: - if (error != 0) { - switch (state) { - case 4: - bus_dmamap_unload(sc->sc_dmatag, - sc_if->sk_cdata.sk_rx_jumbo_map); - case 3: - bus_dmamap_destroy(sc->sc_dmatag, - sc_if->sk_cdata.sk_rx_jumbo_map); - case 2: - bus_dmamem_unmap(sc->sc_dmatag, kva, SK_JMEM); - case 1: - bus_dmamem_free(sc->sc_dmatag, &seg, rseg); - break; - default: - break; - } + error = bus_dmamap_load_mbuf(sc_if->sk_softc->sc_dmatag, dmamap, m, + BUS_DMA_READ|BUS_DMA_NOWAIT); + if (error) { + m_freem(m); + return (ENOBUFS); } - return (error); -} - -/* - * Allocate a jumbo buffer. - */ -void * -sk_jalloc(struct sk_if_softc *sc_if) -{ - struct sk_jpool_entry *entry; - - entry = LIST_FIRST(&sc_if->sk_jfree_listhead); + bus_dmamap_sync(sc_if->sk_softc->sc_dmatag, dmamap, 0, + dmamap->dm_mapsize, BUS_DMASYNC_PREREAD); - if (entry == NULL) - return (NULL); - - LIST_REMOVE(entry, jpool_entries); - LIST_INSERT_HEAD(&sc_if->sk_jinuse_listhead, entry, jpool_entries); - return (sc_if->sk_cdata.sk_jslots[entry->slot]); -} + c = &sc_if->sk_cdata.sk_rx_chain[prod]; + c->sk_mbuf = m; -/* - * Release a jumbo buffer. - */ -void -sk_jfree(caddr_t buf, u_int size, void *arg) -{ - struct sk_jpool_entry *entry; - struct sk_if_softc *sc; - int i; - - /* Extract the softc struct pointer. */ - sc = (struct sk_if_softc *)arg; - - if (sc == NULL) - panic("sk_jfree: can't find softc pointer!"); + r = c->sk_desc; + r->sk_data_lo = htole32(dmamap->dm_segs[0].ds_addr); + r->sk_data_hi = htole32(((u_int64_t)dmamap->dm_segs[0].ds_addr) >> 32); + r->sk_ctl = htole32(dmamap->dm_segs[0].ds_len | SK_RXSTAT); - /* calculate the slot this buffer belongs to */ - i = ((vaddr_t)buf - - (vaddr_t)sc->sk_cdata.sk_jumbo_buf) / SK_JLEN; + SK_CDRXSYNC(sc_if, prod, BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD); - if ((i < 0) || (i >= SK_JSLOTS)) - panic("sk_jfree: asked to free buffer that we don't manage!"); + SK_INC(prod, SK_RX_RING_CNT); + sc_if->sk_cdata.sk_rx_prod = prod; - entry = LIST_FIRST(&sc->sk_jinuse_listhead); - if (entry == NULL) - panic("sk_jfree: buffer not in use!"); - entry->slot = i; - LIST_REMOVE(entry, jpool_entries); - LIST_INSERT_HEAD(&sc->sk_jfree_listhead, entry, jpool_entries); + return (0); } /* @@ -869,6 +725,12 @@ sk_ioctl(struct ifnet *ifp, u_long command, caddr_t data) error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); break; + case SIOCGIFRXR: + error = if_rxr_ioctl((struct if_rxrinfo *)ifr->ifr_data, + NULL, SK_JLEN, &sc_if->sk_cdata.sk_rx_ring); + + break; + default: error = ether_ioctl(ifp, &sc_if->arpcom, command, data); } @@ -997,7 +859,7 @@ sk_attach(struct device *parent, struct device *self, void *aux) struct skc_attach_args *sa = aux; struct ifnet *ifp; caddr_t kva; - int i; + int i, error; sc_if->sk_port = sa->skc_port; sc_if->sk_softc = sc; @@ -1124,10 +986,14 @@ sk_attach(struct device *parent, struct device *self, void *aux) } sc_if->sk_rdata = (struct sk_ring_data *)kva; - /* Try to allocate memory for jumbo buffers. */ - if (sk_alloc_jumbo_mem(sc_if)) { - printf(": jumbo buffer allocation failed\n"); - goto fail_3; + for (i = 0; i < SK_RX_RING_CNT; i++) { + error = bus_dmamap_create(sc->sc_dmatag, SK_JLEN, 1, + SK_JLEN, 0, 0, &sc_if->sk_cdata.sk_rx_map[i]); + if (error != 0) { + printf(": unable to create rx DMA map %d, " + "error = %d\n", i, error); + goto fail_4; + } } ifp = &sc_if->arpcom.ac_if; @@ -1193,12 +1059,18 @@ sk_attach(struct device *parent, struct device *self, void *aux) DPRINTFN(2, ("sk_attach: end\n")); return; +fail_4: + for (i = 0; i < SK_RX_RING_CNT; i++) { + if (sc_if->sk_cdata.sk_rx_map[i] == NULL) + continue; -fail_2: + bus_dmamap_destroy(sc->sc_dmatag, sc_if->sk_cdata.sk_rx_map[i]); + } +fail_3: bus_dmamem_unmap(sc->sc_dmatag, kva, sizeof(struct sk_ring_data)); -fail_1: +fail_2: bus_dmamem_free(sc->sc_dmatag, &sc_if->sk_ring_seg, sc_if->sk_ring_nseg); -fail_3: +fail_1: bus_dmamap_destroy(sc->sc_dmatag, sc_if->sk_ring_map); fail: sc->sk_if[sa->skc_port] = NULL; @@ -1718,45 +1590,44 @@ sk_rxeof(struct sk_if_softc *sc_if) { struct sk_softc *sc = sc_if->sk_softc; struct ifnet *ifp = &sc_if->arpcom.ac_if; + struct if_rxring *rxr = &sc_if->sk_cdata.sk_rx_ring; struct mbuf *m; struct sk_chain *cur_rx; struct sk_rx_desc *cur_desc; - int i, cur, total_len = 0; + int cur, total_len = 0; u_int32_t rxstat, sk_ctl; bus_dmamap_t dmamap; DPRINTFN(2, ("sk_rxeof\n")); - i = sc_if->sk_cdata.sk_rx_prod; - - for (;;) { - cur = i; - + cur = sc_if->sk_cdata.sk_rx_cons; + while (if_rxr_inuse(rxr) > 0) { /* Sync the descriptor */ SK_CDRXSYNC(sc_if, cur, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); - sk_ctl = letoh32(sc_if->sk_rdata->sk_rx_ring[i].sk_ctl); - if ((sk_ctl & SK_RXCTL_OWN) != 0) { - /* Invalidate the descriptor -- it's not ready yet */ - SK_CDRXSYNC(sc_if, cur, BUS_DMASYNC_PREREAD); - sc_if->sk_cdata.sk_rx_prod = i; + cur_rx = &sc_if->sk_cdata.sk_rx_chain[cur]; + if (cur_rx->sk_mbuf == NULL) + break; + + sk_ctl = letoh32(sc_if->sk_rdata->sk_rx_ring[cur].sk_ctl); + if ((sk_ctl & SK_RXCTL_OWN) != 0) break; - } - cur_rx = &sc_if->sk_cdata.sk_rx_chain[cur]; cur_desc = &sc_if->sk_rdata->sk_rx_ring[cur]; - dmamap = sc_if->sk_cdata.sk_rx_jumbo_map; + dmamap = sc_if->sk_cdata.sk_rx_map[cur]; bus_dmamap_sync(sc_if->sk_softc->sc_dmatag, dmamap, 0, dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(sc_if->sk_softc->sc_dmatag, dmamap); - rxstat = letoh32(cur_desc->sk_xmac_rxstat); m = cur_rx->sk_mbuf; cur_rx->sk_mbuf = NULL; - total_len = SK_RXBYTES(letoh32(cur_desc->sk_ctl)); + if_rxr_put(rxr, 1); + SK_INC(cur, SK_RX_RING_CNT); - SK_INC(i, SK_RX_RING_CNT); + total_len = SK_RXBYTES(letoh32(cur_desc->sk_ctl)); + rxstat = letoh32(cur_desc->sk_xmac_rxstat); if ((sk_ctl & (SK_RXCTL_STATUS_VALID | SK_RXCTL_FIRSTFRAG | SK_RXCTL_LASTFRAG)) != (SK_RXCTL_STATUS_VALID | @@ -1765,31 +1636,12 @@ sk_rxeof(struct sk_if_softc *sc_if) total_len > SK_JUMBO_FRAMELEN || sk_rxvalid(sc, rxstat, total_len) == 0) { ifp->if_ierrors++; - sk_newbuf(sc_if, cur, m, dmamap); + m_freem(m); continue; } - /* - * Try to allocate a new jumbo buffer. If that - * fails, copy the packet to mbufs and put the - * jumbo buffer back in the ring so it can be - * re-used. If allocating mbufs fails, then we - * have to drop the packet. - */ - if (sk_newbuf(sc_if, cur, NULL, dmamap) == ENOBUFS) { - struct mbuf *m0; - m0 = m_devget(mtod(m, char *), total_len, ETHER_ALIGN, - ifp); - sk_newbuf(sc_if, cur, m, dmamap); - if (m0 == NULL) { - ifp->if_ierrors++; - continue; - } - m = m0; - } else { - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = m->m_len = total_len; - } + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = m->m_len = total_len; ifp->if_ipackets++; @@ -1801,6 +1653,9 @@ sk_rxeof(struct sk_if_softc *sc_if) /* pass it on. */ ether_input_mbuf(ifp, m); } + sc_if->sk_cdata.sk_rx_cons = cur; + + sk_fill_rx_ring(sc_if); } void @@ -2570,6 +2425,7 @@ sk_stop(struct sk_if_softc *sc_if, int softonly) { struct sk_softc *sc = sc_if->sk_softc; struct ifnet *ifp = &sc_if->arpcom.ac_if; + bus_dmamap_t dmamap; struct sk_txmap_entry *dma; int i; u_int32_t val; @@ -2660,6 +2516,10 @@ sk_stop(struct sk_if_softc *sc_if, int softonly) /* Free RX and TX mbufs still in the queues. */ for (i = 0; i < SK_RX_RING_CNT; i++) { if (sc_if->sk_cdata.sk_rx_chain[i].sk_mbuf != NULL) { + dmamap = sc_if->sk_cdata.sk_rx_map[i]; + bus_dmamap_sync(sc_if->sk_softc->sc_dmatag, dmamap, 0, + dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(sc_if->sk_softc->sc_dmatag, dmamap); m_freem(sc_if->sk_cdata.sk_rx_chain[i].sk_mbuf); sc_if->sk_cdata.sk_rx_chain[i].sk_mbuf = NULL; } diff --git a/sys/dev/pci/if_skvar.h b/sys/dev/pci/if_skvar.h index c14b1754695..987a35c5804 100644 --- a/sys/dev/pci/if_skvar.h +++ b/sys/dev/pci/if_skvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_skvar.h,v 1.8 2013/03/07 06:13:31 brad Exp $ */ +/* $OpenBSD: if_skvar.h,v 1.9 2014/08/20 00:50:45 dlg Exp $ */ /* $NetBSD: if_skvar.h,v 1.6 2005/05/30 04:35:22 christos Exp $ */ /*- @@ -26,7 +26,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -/* $OpenBSD: if_skvar.h,v 1.8 2013/03/07 06:13:31 brad Exp $ */ +/* $OpenBSD: if_skvar.h,v 1.9 2014/08/20 00:50:45 dlg Exp $ */ /* * Copyright (c) 1997, 1998, 1999, 2000 @@ -81,11 +81,6 @@ #ifndef _DEV_PCI_IF_SKVAR_H_ #define _DEV_PCI_IF_SKVAR_H_ -struct sk_jpool_entry { - int slot; - LIST_ENTRY(sk_jpool_entry) jpool_entries; -}; - struct sk_chain { void *sk_desc; struct mbuf *sk_mbuf; @@ -111,17 +106,12 @@ struct sk_chain_data { struct sk_chain sk_rx_chain[SK_RX_RING_CNT]; struct sk_txmap_entry *sk_tx_map[SK_TX_RING_CNT]; bus_dmamap_t sk_rx_map[SK_RX_RING_CNT]; - bus_dmamap_t sk_rx_jumbo_map; int sk_tx_prod; int sk_tx_cons; int sk_tx_cnt; int sk_rx_prod; int sk_rx_cons; - int sk_rx_cnt; - /* Stick the jumbo mem management stuff here too. */ - caddr_t sk_jslots[SK_JSLOTS]; - void *sk_jumbo_buf; - + struct if_rxring sk_rx_ring; }; struct sk_ring_data { @@ -223,8 +213,6 @@ struct sk_if_softc { int sk_ring_nseg; struct sk_softc *sk_softc; /* parent controller */ int sk_tx_bmu; /* TX BMU register */ - LIST_HEAD(__sk_jfreehead, sk_jpool_entry) sk_jfree_listhead; - LIST_HEAD(__sk_jinusehead, sk_jpool_entry) sk_jinuse_listhead; SIMPLEQ_HEAD(__sk_txmaphead, sk_txmap_entry) sk_txmap_head; }; -- 2.20.1