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.
This commit is contained in:
thorpej 2020-03-08 22:26:03 +00:00
parent 23047d1d4d
commit a67cfe799f
2 changed files with 50 additions and 47 deletions

View File

@ -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);
m_freem(m);
m = mnew;
if (bus_dmamap_load_mbuf(sc->sc_dmat, sd->sd_map, m,
BUS_DMA_NOWAIT))
goto oactive1;
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;
}
}
if ((TX_ENTRIES - cnt) < 4)
goto oactive;
IFQ_DEQUEUE(&ifp->if_snd, m);
if (mnew != NULL) {
m_freem(m);
m = mnew;
}
/*
* 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;
}
/*

View File

@ -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 <aaron@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) \