From 712e6aecb0efa100cda1ef6f8a50b05be182dd94 Mon Sep 17 00:00:00 2001 From: kettenis Date: Fri, 2 Jan 2015 16:20:11 +0000 Subject: [PATCH] Still locks up under load, but otherwise fairly functional. --- sys/dev/pci/if_nep.c | 159 ++++++++++++++++++++++++++++--------------- 1 file changed, 103 insertions(+), 56 deletions(-) diff --git a/sys/dev/pci/if_nep.c b/sys/dev/pci/if_nep.c index 65d9632d7b7..f9e3080c6ea 100644 --- a/sys/dev/pci/if_nep.c +++ b/sys/dev/pci/if_nep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_nep.c,v 1.6 2014/12/29 19:33:34 kettenis Exp $ */ +/* $OpenBSD: if_nep.c,v 1.7 2015/01/02 16:20:11 kettenis Exp $ */ /* * Copyright (c) 2014 Mark Kettenis * @@ -424,9 +424,10 @@ void nep_fill_rx_ring(struct nep_softc *); void nep_up(struct nep_softc *); void nep_down(struct nep_softc *); void nep_iff(struct nep_softc *); -int nep_encap(struct nep_softc *, struct mbuf *, int *); +int nep_encap(struct nep_softc *, struct mbuf **, int *); void nep_start(struct ifnet *); +void nep_watchdog(struct ifnet *); void nep_tick(void *); int nep_ioctl(struct ifnet *, u_long, caddr_t); @@ -534,6 +535,7 @@ nep_attach(struct device *parent, struct device *self, void *aux) ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; ifp->if_ioctl = nep_ioctl; ifp->if_start = nep_start; + ifp->if_watchdog = nep_watchdog; mii->mii_ifp = ifp; mii->mii_readreg = nep_mii_readreg; @@ -710,9 +712,6 @@ nep_intr(void *arg) if ((sv0 | sv1 | sv2) == 0) return (0); - printf("%s: %s %llx %llx %llx\n", sc->sc_dev.dv_xname, - __func__, sv0, sv1, sv2); - if (sv0 & (1ULL << LDN_TXDMA(sc->sc_port))) { nep_tx_proc(sc); rearm = 1; @@ -725,6 +724,9 @@ nep_intr(void *arg) if (rearm) nep_write(sc, LDGIMGN(sc->sc_port), LDGIMGN_ARM | 2); + else + printf("%s: %s %llx %llx %llx\n", sc->sc_dev.dv_xname, + __func__, sv0, sv1, sv2); return (1); } @@ -745,7 +747,7 @@ nep_rx_proc(struct nep_softc *sc) int idx, len, i; val = nep_read(sc, RX_DMA_CTL_STAT(sc->sc_port)); - printf("RX_DMA_CTL_STAT: %llx\n", val); +// printf("RX_DMA_CTL_STAT: %llx\n", val); nep_write(sc, RX_DMA_CTL_STAT(sc->sc_port), RX_DMA_CTL_STAT_RCRTHRES | RX_DMA_CTL_STAT_RCRTO); @@ -758,45 +760,63 @@ nep_rx_proc(struct nep_softc *sc) KASSERT(idx < NEP_NRCDESC); rxd = letoh64(sc->sc_rcdesc[idx]); - printf("XXX 0x%016llx\n", rxd); +// printf("XXX 0x%016llx\n", rxd); addr = (rxd & RXD_PKT_BUF_ADDR_MASK) << RXD_PKT_BUF_ADDR_SHIFT; len = (rxd & RXD_L2_LEN_MASK) >> RXD_L2_LEN_SHIFT; page = addr & ~PAGE_MASK; off = addr & PAGE_MASK; - for (i = 0; i < sc->sc_rx_prod; i++) { - if (sc->sc_rb[i].nb_map->dm_segs[0].ds_addr == page) { - printf("bingo!\n"); + block = NULL; + for (i = 0; i < NEP_NRBDESC; i++) { + if (sc->sc_rb[i].nb_block && + sc->sc_rb[i].nb_map->dm_segs[0].ds_addr == page) { block = sc->sc_rb[i].nb_block; - MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m == NULL) - break; - MEXTADD(m, block + off, 2048, M_EXTWR, - nep_extfree, sc); - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = m->m_len = len; - m->m_data += ETHER_ALIGN; + break; + } + } + if (block == NULL) { + panic("oops!\n"); + break; + } + + bus_dmamap_unload(sc->sc_dmat, sc->sc_rb[i].nb_map); + sc->sc_rb[i].nb_block = NULL; + + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == NULL) { + printf("oops2!\n"); + break; + } + MEXTADD(m, block + off, PAGE_SIZE, M_EXTWR, nep_extfree, block); + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = m->m_len = len; + m->m_data += ETHER_ALIGN; - ifp->if_ipackets++; + ifp->if_ipackets++; #if NBPFILTER > 0 - if (ifp->if_bpf) - bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN); + if (ifp->if_bpf) + bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN); #endif - ether_input_mbuf(ifp, m); - break; - } - } + ether_input_mbuf(ifp, m); + + if_rxr_put(&sc->sc_rx_ring, 1); if ((rxd & RXD_MULTI) == 0) { count--; pktread++; } ptrread++; sc->sc_rx_cons++; - sc->sc_rx_cons %= NEP_NRCDESC; + if (sc->sc_rx_cons >= NEP_NRCDESC) + sc->sc_rx_cons = 0; } + bus_dmamap_sync(sc->sc_dmat, NEP_DMA_MAP(sc->sc_rcring), 0, + NEP_DMA_LEN(sc->sc_rcring), BUS_DMASYNC_PREREAD); + + nep_fill_rx_ring(sc); + val = pktread | (ptrread << RX_DMA_CTL_STAT_PTRREAD_SHIFT); val |= RX_DMA_CTL_STAT_MEX; nep_write(sc, RX_DMA_CTL_STAT(sc->sc_port), val); @@ -805,6 +825,7 @@ nep_rx_proc(struct nep_softc *sc) void nep_extfree(caddr_t buf, u_int size, void *arg) { + pool_put(nep_block_pool, arg); } void @@ -817,7 +838,7 @@ nep_tx_proc(struct nep_softc *sc) int idx; val = nep_read(sc, TX_CS(sc->sc_port)); - printf("TX_CS: %llx\n", val); +// printf("TX_CS: %llx\n", val); pkt_cnt = (val & TX_CS_PKT_CNT_MASK) >> TX_CS_PKT_CNT_SHIFT; count = (pkt_cnt - sc->sc_pkt_cnt); count &= (TX_CS_PKT_CNT_MASK >> TX_CS_PKT_CNT_SHIFT); @@ -843,7 +864,8 @@ nep_tx_proc(struct nep_softc *sc) sc->sc_tx_cnt--; sc->sc_tx_cons++; - sc->sc_tx_cons &= (NEP_NTXDESC - 1); + if (sc->sc_tx_cons >= NEP_NTXDESC) + sc->sc_tx_cons = 0; } if (sc->sc_tx_cnt == 0) @@ -943,7 +965,7 @@ nep_init_rx_channel(struct nep_softc *sc, int chan) nep_write(sc, RBR_CFIG_A(chan), val); val = RBR_CFIG_B_BLKSIZE_8K; - val |= RBR_CFIG_B_BUFSZ0_2K | RBR_CFIG_B_VLD0; + val |= RBR_CFIG_B_BUFSZ1_8K | RBR_CFIG_B_VLD1; nep_write(sc, RBR_CFIG_B(chan), val); val = NEP_DMA_DVA(sc->sc_rcring); @@ -1208,8 +1230,9 @@ nep_iff(struct nep_softc *sc) } int -nep_encap(struct nep_softc *sc, struct mbuf *m, int *idx) +nep_encap(struct nep_softc *sc, struct mbuf **m0, int *idx) { + struct mbuf *m = *m0; struct nep_txbuf_hdr *nh; uint64_t txd; bus_dmamap_t map; @@ -1217,13 +1240,13 @@ nep_encap(struct nep_softc *sc, struct mbuf *m, int *idx) int len, pad; int err; - printf("%s: %s\n", sc->sc_dev.dv_xname, __func__); +// printf("%s: %s\n", sc->sc_dev.dv_xname, __func__); // printf("TX_CS: %llx\n", nep_read(sc, TX_CS(sc->sc_port))); // printf("TX_RNG_ERR_LOGH: %llx\n", // nep_read(sc, TX_RNG_ERR_LOGH(sc->sc_port))); // printf("TX_RNG_ERR_LOGL: %llx\n", // nep_read(sc, TX_RNG_ERR_LOGL(sc->sc_port))); - printf("SYS_ERR_STAT %llx\n", nep_read(sc, SYS_ERR_STAT)); +// printf("SYS_ERR_STAT %llx\n", nep_read(sc, SYS_ERR_STAT)); // printf("ZCP_INT_STAT %llx\n", nep_read(sc, ZCP_INT_STAT)); // printf("TXC_INT_STAT_DBG %llx\n", nep_read(sc, TXC_INT_STAT_DBG)); // printf("TXC_PKT_STUFFED: %llx\n", @@ -1238,22 +1261,24 @@ nep_encap(struct nep_softc *sc, struct mbuf *m, int *idx) // nep_read(sc, XTXMAC_STATUS(sc->sc_port))); // printf("XRXMAC_STATUS: %llx\n", // nep_read(sc, XRXMAC_STATUS(sc->sc_port))); - printf("RXMAC_BT_CNT: %llx\n", - nep_read(sc, RXMAC_BT_CNT(sc->sc_port))); - printf("TXMAC_FRM_CNT: %llx\n", - nep_read(sc, TXMAC_FRM_CNT(sc->sc_port))); - printf("TXMAC_BYTE_CNT: %llx\n", - nep_read(sc, TXMAC_BYTE_CNT(sc->sc_port))); +// printf("RXMAC_BT_CNT: %llx\n", +// nep_read(sc, RXMAC_BT_CNT(sc->sc_port))); +// printf("TXMAC_FRM_CNT: %llx\n", +// nep_read(sc, TXMAC_FRM_CNT(sc->sc_port))); +// printf("TXMAC_BYTE_CNT: %llx\n", +// nep_read(sc, TXMAC_BYTE_CNT(sc->sc_port))); // printf("RBR_STAT: %llx\n", // nep_read(sc, RBR_STAT(sc->sc_port))); - printf("RBR_HDL: %llx\n", - nep_read(sc, RBR_HDL(sc->sc_port))); +// printf("RBR_HDL: %llx\n", +// nep_read(sc, RBR_HDL(sc->sc_port))); // printf("RCRSTAT_A: %llx\n", // nep_read(sc, RCRSTAT_A(sc->sc_port))); // printf("RCRSTAT_C: %llx\n", // nep_read(sc, RCRSTAT_C(sc->sc_port))); - printf("RX_DMA_CTL_STAT: %llx\n", - nep_read(sc, RX_DMA_CTL_STAT(sc->sc_port))); +// printf("RX_DMA_CTL_STAT: %llx\n", +// nep_read(sc, RX_DMA_CTL_STAT(sc->sc_port))); + +// printf("mbuf %d %d %d\n", M_LEADINGSPACE(m), M_TRAILINGSPACE(m), m->m_len); /* * MAC does not support padding of transmit packets that are @@ -1265,15 +1290,20 @@ nep_encap(struct nep_softc *sc, struct mbuf *m, int *idx) padlen = (ETHER_MIN_LEN - ETHER_CRC_LEN) - m->m_pkthdr.len; MGET(n, M_DONTWAIT, MT_DATA); - if (n == NULL) + if (n == NULL) { + m_freem(m); return (ENOBUFS); + } memset(mtod(n, caddr_t), 0, padlen); n->m_len = padlen; m_cat(m, n); m->m_pkthdr.len += padlen; } - pad = mtod(m, u_long) % 16; + if (M_LEADINGSPACE(m) < 16) + pad = 0; + else + pad = mtod(m, u_long) % 16; len = m->m_pkthdr.len + pad; M_PREPEND(m, sizeof(*nh) + pad, M_DONTWAIT); if (m == NULL) @@ -1286,12 +1316,9 @@ nep_encap(struct nep_softc *sc, struct mbuf *m, int *idx) map = sc->sc_txbuf[cur].nb_map; err = bus_dmamap_load_mbuf(sc->sc_dmat, map, m, BUS_DMA_NOWAIT); - m_adj(m, sizeof(*nh) + pad); - if (err) - return (ENOBUFS); - - if (map->dm_nsegs > (NEP_NTXDESC - sc->sc_tx_cnt - 2)) { - bus_dmamap_unload(sc->sc_dmat, map); + if (err) { + /* XXX defrag */ + m_freem(m); return (ENOBUFS); } @@ -1302,7 +1329,7 @@ nep_encap(struct nep_softc *sc, struct mbuf *m, int *idx) txd = TXD_SOP | TXD_MARK; txd |= ((uint64_t)map->dm_nsegs << TXD_NUM_PTR_SHIFT); for (i = 0; i < map->dm_nsegs; i++) { - +// printf("frag %d 0x%08lx %ld\n", i, map->dm_segs[i].ds_addr, map->dm_segs[i].ds_len); txd |= ((uint64_t)map->dm_segs[i].ds_len << TXD_TR_LEN_SHIFT); txd |= map->dm_segs[i].ds_addr; sc->sc_txdesc[frag] = htole64(txd); @@ -1334,6 +1361,10 @@ nep_encap(struct nep_softc *sc, struct mbuf *m, int *idx) // nep_read(sc, TX_RNG_ERR_LOGH(sc->sc_port))); // printf("TX_RNG_ERR_LOGL: %llx\n", // nep_read(sc, TX_RNG_ERR_LOGL(sc->sc_port))); + + m_adj(m, sizeof(*nh) + pad); + *m0 = m; + return (0); } @@ -1352,12 +1383,12 @@ nep_start(struct ifnet *ifp) return; idx = sc->sc_tx_prod; - while (sc->sc_tx_cnt < NEP_NTXDESC) { + for (;;) { IFQ_POLL(&ifp->if_snd, m); if (m == NULL) break; - if (nep_encap(sc, m, &idx)) { + if (sc->sc_tx_cnt >= (NEP_NTXDESC - NEP_NTXSEGS)) { ifp->if_flags |= IFF_OACTIVE; break; } @@ -1365,6 +1396,9 @@ nep_start(struct ifnet *ifp) /* Now we are committed to transmit the packet. */ IFQ_DEQUEUE(&ifp->if_snd, m); + if (nep_encap(sc, &m, &idx)) + break; + #if NBPFILTER > 0 if (ifp->if_bpf) bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); @@ -1379,6 +1413,12 @@ nep_start(struct ifnet *ifp) } } +void +nep_watchdog(struct ifnet *ifp) +{ + printf("%s\n", __func__); +} + void nep_tick(void *arg) { @@ -1457,17 +1497,24 @@ nep_fill_rx_ring(struct nep_softc *sc) rb = &sc->sc_rb[desc]; block = pool_get(nep_block_pool, PR_NOWAIT); - if (block == NULL) + if (block == NULL) { + printf("oops3\n"); break; - rb->nb_block = block; + } err = bus_dmamap_load(sc->sc_dmat, rb->nb_map, block, PAGE_SIZE, NULL, BUS_DMA_NOWAIT); - if (err) + if (err) { + printf("oops4\n"); + pool_put(nep_block_pool, block); break; + } + rb->nb_block = block; sc->sc_rbdesc[desc++] = htole32(rb->nb_map->dm_segs[0].ds_addr >> 12); count++; slots--; + if (desc >= NEP_NRBDESC) + desc = 0; } if_rxr_put(&sc->sc_rx_ring, slots); if (count > 0) { -- 2.20.1