Module Name:    src
Committed By:   thorpej
Date:           Sun Mar  8 22:26:03 UTC 2020

Modified Files:
        src/sys/dev/pci: if_txp.c if_txpreg.h

Log Message:
Give each Tx DMA map 16 DMA segments rather than the previous absurdly large
number, and structure the loop in txp_start() similarly to other drivers
(e.g. ste_start() in the ste(4) driver).  Similar in spirit to OpenBSD's
rev 1.126, but implemented a bit differently.


To generate a diff of this commit:
cvs rdiff -u -r1.67 -r1.68 src/sys/dev/pci/if_txp.c
cvs rdiff -u -r1.8 -r1.9 src/sys/dev/pci/if_txpreg.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/if_txp.c
diff -u src/sys/dev/pci/if_txp.c:1.67 src/sys/dev/pci/if_txp.c:1.68
--- src/sys/dev/pci/if_txp.c:1.67	Sun Mar  8 20:49:31 2020
+++ src/sys/dev/pci/if_txp.c	Sun Mar  8 22:26:03 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: if_txp.c,v 1.67 2020/03/08 20:49:31 thorpej Exp $ */
+/* $NetBSD: if_txp.c,v 1.68 2020/03/08 22:26:03 thorpej Exp $ */
 
 /*
  * Copyright (c) 2001
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_txp.c,v 1.67 2020/03/08 20:49:31 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_txp.c,v 1.68 2020/03/08 22:26:03 thorpej Exp $");
 
 #include "opt_inet.h"
 
@@ -978,8 +978,8 @@ txp_alloc_rings(struct txp_softc *sc)
 	sc->sc_txhir.r_off = &sc->sc_hostvar->hv_tx_hi_desc_read_idx;
 	for (i = 0; i < TX_ENTRIES; i++) {
 		if (bus_dmamap_create(sc->sc_dmat, TXP_MAX_PKTLEN,
-		    TX_ENTRIES - 4, TXP_MAX_SEGLEN, 0,
-		    BUS_DMA_NOWAIT, &sc->sc_txd[i].sd_map) != 0) {
+		    TXP_MAXTXSEGS, TXP_MAX_SEGLEN, 0, BUS_DMA_NOWAIT,
+		    &sc->sc_txd[i].sd_map) != 0) {
 			for (j = 0; j < i; j++) {
 				bus_dmamap_destroy(sc->sc_dmat,
 				    sc->sc_txd[j].sd_map);
@@ -1403,7 +1403,8 @@ txp_start(struct ifnet *ifp)
 	struct txp_frag_desc *fxd;
 	struct mbuf *m, *mnew;
 	struct txp_swdesc *sd;
-	uint32_t firstprod, firstcnt, prod, cnt, i;
+	uint32_t prod, cnt, i;
+	int error;
 
 	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
 		return;
@@ -1412,41 +1413,66 @@ txp_start(struct ifnet *ifp)
 	cnt = r->r_cnt;
 
 	while (1) {
+		if (cnt >= TX_ENTRIES - TXP_MAXTXSEGS - 4) {
+			ifp->if_flags |= IFF_OACTIVE;
+			break;
+		}
+
 		IFQ_POLL(&ifp->if_snd, m);
 		if (m == NULL)
 			break;
 		mnew = NULL;
 
-		firstprod = prod;
-		firstcnt = cnt;
-
 		sd = sc->sc_txd + prod;
-		sd->sd_mbuf = m;
 
+		/*
+		 * Load the DMA map.  If this fails, the packet either
+		 * didn't fit in the alloted number of segments, or we
+		 * were short on resources.  In this case, we'll copy
+		 * and try again.
+		 */
 		if (bus_dmamap_load_mbuf(sc->sc_dmat, sd->sd_map, m,
-		    BUS_DMA_NOWAIT)) {
+		    BUS_DMA_NOWAIT) != 0) {
 			MGETHDR(mnew, M_DONTWAIT, MT_DATA);
-			if (mnew == NULL)
-				goto oactive1;
+			if (mnew == NULL) {
+				printf("%s: unable to allocate Tx mbuf\n",
+				    device_xname(sc->sc_dev));
+				break;
+			}
 			if (m->m_pkthdr.len > MHLEN) {
 				MCLGET(mnew, M_DONTWAIT);
 				if ((mnew->m_flags & M_EXT) == 0) {
+					printf("%s: unable to allocate Tx "
+					    "cluster\n",
+					    device_xname(sc->sc_dev));
 					m_freem(mnew);
-					goto oactive1;
+					break;
 				}
 			}
 			m_copydata(m, 0, m->m_pkthdr.len, mtod(mnew, void *));
 			mnew->m_pkthdr.len = mnew->m_len = m->m_pkthdr.len;
-			IFQ_DEQUEUE(&ifp->if_snd, m);
+			error = bus_dmamap_load_mbuf(sc->sc_dmat, sd->sd_map,
+			    mnew, BUS_DMA_NOWAIT);
+			if (error) {
+				printf("%s: unable to load Tx buffer, "
+				    "error = %d\n", device_xname(sc->sc_dev),
+				    error);
+				m_freem(mnew);
+				break;
+			}
+		}
+
+		IFQ_DEQUEUE(&ifp->if_snd, m);
+		if (mnew != NULL) {
 			m_freem(m);
 			m = mnew;
-			if (bus_dmamap_load_mbuf(sc->sc_dmat, sd->sd_map, m,
-			    BUS_DMA_NOWAIT))
-				goto oactive1;
 		}
 
-		if ((TX_ENTRIES - cnt) < 4)
-			goto oactive;
+		/*
+		 * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET.
+		 */
+
+		sd->sd_mbuf = m;
 
 		txd = r->r_desc + prod;
 		txdidx = prod;
@@ -1461,9 +1487,6 @@ txp_start(struct ifnet *ifp)
 		if (++prod == TX_ENTRIES)
 			prod = 0;
 
-		if (++cnt >= (TX_ENTRIES - 4))
-			goto oactive;
-
 		if (vlan_has_tag(m))
 			txd->tx_pflags = TX_PFLAGS_VLAN |
 			  (htons(vlan_get_tag(m)) << TX_PFLAGS_VLANTAG_S);
@@ -1484,13 +1507,6 @@ txp_start(struct ifnet *ifp)
 
 		fxd = (struct txp_frag_desc *)(r->r_desc + prod);
 		for (i = 0; i < sd->sd_map->dm_nsegs; i++) {
-			if (++cnt >= (TX_ENTRIES - 4)) {
-				bus_dmamap_sync(sc->sc_dmat, sd->sd_map,
-				    0, sd->sd_map->dm_mapsize,
-				    BUS_DMASYNC_POSTWRITE);
-				goto oactive;
-			}
-
 			fxd->frag_flags = FRAG_FLAGS_TYPE_FRAG |
 			    FRAG_FLAGS_VALID;
 			fxd->frag_rsvd1 = 0;
@@ -1514,13 +1530,6 @@ txp_start(struct ifnet *ifp)
 
 		}
 
-		/*
-		 * if mnew isn't NULL, we already dequeued and copied
-		 * the packet.
-		 */
-		if (mnew == NULL)
-			IFQ_DEQUEUE(&ifp->if_snd, m);
-
 		ifp->if_timer = 5;
 
 		bpf_mtap(ifp, m, BPF_D_OUT);
@@ -1553,14 +1562,6 @@ txp_start(struct ifnet *ifp)
 
 	r->r_prod = prod;
 	r->r_cnt = cnt;
-	return;
-
-oactive:
-	bus_dmamap_unload(sc->sc_dmat, sd->sd_map);
-oactive1:
-	ifp->if_flags |= IFF_OACTIVE;
-	r->r_prod = firstprod;
-	r->r_cnt = firstcnt;
 }
 
 /*

Index: src/sys/dev/pci/if_txpreg.h
diff -u src/sys/dev/pci/if_txpreg.h:1.8 src/sys/dev/pci/if_txpreg.h:1.9
--- src/sys/dev/pci/if_txpreg.h:1.8	Sun Mar  8 20:49:31 2020
+++ src/sys/dev/pci/if_txpreg.h	Sun Mar  8 22:26:03 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: if_txpreg.h,v 1.8 2020/03/08 20:49:31 thorpej Exp $ */
+/* $NetBSD: if_txpreg.h,v 1.9 2020/03/08 22:26:03 thorpej Exp $ */
 
 /*
  * Copyright (c) 2001 Aaron Campbell <aa...@monkey.org>.
@@ -616,6 +616,8 @@ struct txp_fw_section_header {
 #define	TXP_MAX_SEGLEN	0xffff
 #define	TXP_MAX_PKTLEN	0x0800
 
+#define	TXP_MAXTXSEGS	16
+
 #define	WRITE_REG(sc,reg,val) \
     bus_space_write_4((sc)->sc_bt, (sc)->sc_bh, reg, val)
 #define	READ_REG(sc,reg) \

Reply via email to