From: dlg Date: Thu, 1 Jun 2017 23:17:01 +0000 (+0000) Subject: reorder ops in sk_start to avoid possibly rolling back ifq_deq. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=a79cb044b6e71bc5058d4f279f2c10c1039f2303;p=openbsd reorder ops in sk_start to avoid possibly rolling back ifq_deq. instead of checking for space after beggining to deq a packet, check for space before committing to handling a packet. this means we can use ifq_dequeue instead of ifq_deq_begin/commit/rollback. ok mikeb@ --- diff --git a/sys/dev/pci/if_sk.c b/sys/dev/pci/if_sk.c index 180bfaa8af9..0172cd92ce3 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.186 2017/01/22 10:17:38 dlg Exp $ */ +/* $OpenBSD: if_sk.c,v 1.187 2017/06/01 23:17:01 dlg Exp $ */ /* * Copyright (c) 1997, 1998, 1999, 2000 @@ -1405,30 +1405,20 @@ sk_encap(struct sk_if_softc *sc_if, struct mbuf *m_head, u_int32_t *txidx) cur = frag = *txidx; -#ifdef SK_DEBUG - if (skdebug >= 2) - sk_dump_mbuf(m_head); -#endif - - /* - * Start packing the mbufs in this chain into - * the fragment pointers. Stop when we run out - * of fragments or hit the end of the mbuf chain. - */ - if (bus_dmamap_load_mbuf(sc->sc_dmatag, txmap, m_head, - BUS_DMA_NOWAIT)) { - DPRINTFN(2, ("sk_encap: dmamap failed\n")); - return (ENOBUFS); - } + switch (bus_dmamap_load_mbuf(sc->sc_dmatag, txmap, m_head, + BUS_DMA_STREAMING | BUS_DMA_NOWAIT)) { + case 0: + break; - if (txmap->dm_nsegs > (SK_TX_RING_CNT - sc_if->sk_cdata.sk_tx_cnt - 2)) { - DPRINTFN(2, ("sk_encap: too few descriptors free\n")); - bus_dmamap_unload(sc->sc_dmatag, txmap); - return (ENOBUFS); + case EFBIG: /* mbuf chain is too fragmented */ + if (m_defrag(m_head, M_DONTWAIT) == 0 && + bus_dmamap_load_mbuf(sc->sc_dmatag, txmap, m_head, + BUS_DMA_STREAMING | BUS_DMA_NOWAIT) == 0) + break; + default: + return (1); } - DPRINTFN(2, ("sk_encap: dm_nsegs=%d\n", txmap->dm_nsegs)); - /* Sync the DMA map. */ bus_dmamap_sync(sc->sc_dmatag, txmap, 0, txmap->dm_mapsize, BUS_DMASYNC_PREWRITE); @@ -1490,12 +1480,18 @@ sk_start(struct ifnet *ifp) struct sk_softc *sc = sc_if->sk_softc; struct mbuf *m_head = NULL; u_int32_t idx = sc_if->sk_cdata.sk_tx_prod; - int pkts = 0; + int post = 0; DPRINTFN(2, ("sk_start\n")); - while (sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf == NULL) { - m_head = ifq_deq_begin(&ifp->if_snd); + for (;;) { + if (sc_if->sk_cdata.sk_tx_cnt + SK_NTXSEG + 1 > + SK_TX_RING_CNT) { + ifq_set_oactive(&ifp->if_snd); + break; + } + + m_head = ifq_dequeue(&ifp->if_snd); if (m_head == NULL) break; @@ -1505,14 +1501,11 @@ sk_start(struct ifnet *ifp) * for the NIC to drain the ring. */ if (sk_encap(sc_if, m_head, &idx)) { - ifq_deq_rollback(&ifp->if_snd, m_head); - ifq_set_oactive(&ifp->if_snd); - break; + m_freem(m_head); + continue; } /* now we are committed to transmit the packet */ - ifq_deq_commit(&ifp->if_snd, m_head); - pkts++; /* * If there's a BPF listener, bounce a copy of this frame @@ -1522,18 +1515,18 @@ sk_start(struct ifnet *ifp) if (ifp->if_bpf) bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT); #endif + + post = 1; } - if (pkts == 0) + if (post == 0) return; /* Transmit */ - if (idx != sc_if->sk_cdata.sk_tx_prod) { - sc_if->sk_cdata.sk_tx_prod = idx; - CSR_WRITE_4(sc, sc_if->sk_tx_bmu, SK_TXBMU_TX_START); + sc_if->sk_cdata.sk_tx_prod = idx; + CSR_WRITE_4(sc, sc_if->sk_tx_bmu, SK_TXBMU_TX_START); - /* Set a timeout in case the chip goes out to lunch. */ - ifp->if_timer = SK_TX_TIMEOUT; - } + /* Set a timeout in case the chip goes out to lunch. */ + ifp->if_timer = SK_TX_TIMEOUT; }