re(4) driver:
- TSO support. - fix some error handling. - remove mysterious RTK_NTXSEGS and use more appropriate values for bus_dmamap_create. - if we need more than all of our tx descriptors in order to transmit a packet, just drop it rather than retrying infinitely.
This commit is contained in:
parent
9482bc7356
commit
5ef6b21b78
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: rtl8169.c,v 1.12 2005/02/27 00:27:02 perry Exp $ */
|
||||
/* $NetBSD: rtl8169.c,v 1.13 2005/03/12 08:01:51 yamt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997, 1998-2003
|
||||
@ -130,6 +130,10 @@
|
||||
#include <net/if_media.h>
|
||||
#include <net/if_vlanvar.h>
|
||||
|
||||
#include <netinet/in_systm.h> /* XXX for IP_MAXPACKET */
|
||||
#include <netinet/in.h> /* XXX for IP_MAXPACKET */
|
||||
#include <netinet/ip.h> /* XXX for IP_MAXPACKET */
|
||||
|
||||
#if NBPFILTER > 0
|
||||
#include <net/bpf.h>
|
||||
#endif
|
||||
@ -659,8 +663,10 @@ re_attach(struct rtk_softc *sc)
|
||||
|
||||
/* Create DMA maps for TX buffers */
|
||||
for (i = 0; i < RTK_TX_DESC_CNT; i++) {
|
||||
error = bus_dmamap_create(sc->sc_dmat, MCLBYTES * RTK_NTXSEGS,
|
||||
RTK_NTXSEGS, MCLBYTES, 0, BUS_DMA_ALLOCNOW,
|
||||
error = bus_dmamap_create(sc->sc_dmat,
|
||||
round_page(IP_MAXPACKET),
|
||||
RTK_TX_DESC_CNT - 4, RTK_TDESC_CMD_FRAGLEN,
|
||||
0, BUS_DMA_ALLOCNOW,
|
||||
&sc->rtk_ldata.rtk_tx_dmamap[i]);
|
||||
if (error) {
|
||||
aprint_error("%s: can't create DMA map for TX\n",
|
||||
@ -732,7 +738,8 @@ re_attach(struct rtk_softc *sc)
|
||||
ifp->if_start = re_start;
|
||||
ifp->if_stop = re_stop;
|
||||
ifp->if_capabilities |=
|
||||
IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4;
|
||||
IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4 |
|
||||
IFCAP_TSOv4;
|
||||
ifp->if_watchdog = re_watchdog;
|
||||
ifp->if_init = re_init;
|
||||
if (sc->rtk_type == RTK_8169)
|
||||
@ -1485,7 +1492,7 @@ done:
|
||||
}
|
||||
|
||||
static int
|
||||
re_encap(struct rtk_softc *sc, struct mbuf *m_head, int *idx)
|
||||
re_encap(struct rtk_softc *sc, struct mbuf *m, int *idx)
|
||||
{
|
||||
bus_dmamap_t map;
|
||||
int error, i, curidx;
|
||||
@ -1503,27 +1510,42 @@ re_encap(struct rtk_softc *sc, struct mbuf *m_head, int *idx)
|
||||
* chip. I'm not sure if this is a requirement or a bug.)
|
||||
*/
|
||||
|
||||
rtk_flags = 0;
|
||||
if ((m->m_pkthdr.csum_flags & M_CSUM_TSOv4) != 0) {
|
||||
u_int32_t segsz = m->m_pkthdr.segsz;
|
||||
|
||||
if (m_head->m_pkthdr.csum_flags & M_CSUM_IPv4)
|
||||
rtk_flags |= RTK_TDESC_CMD_IPCSUM;
|
||||
if (m_head->m_pkthdr.csum_flags & M_CSUM_TCPv4)
|
||||
rtk_flags |= RTK_TDESC_CMD_TCPCSUM;
|
||||
if (m_head->m_pkthdr.csum_flags & M_CSUM_UDPv4)
|
||||
rtk_flags |= RTK_TDESC_CMD_UDPCSUM;
|
||||
rtk_flags = RTK_TDESC_CMD_LGSEND |
|
||||
(segsz << RTK_TDESC_CMD_MSSVAL_SHIFT);
|
||||
} else {
|
||||
rtk_flags = 0;
|
||||
if (m->m_pkthdr.csum_flags & M_CSUM_IPv4)
|
||||
rtk_flags |= RTK_TDESC_CMD_IPCSUM;
|
||||
if (m->m_pkthdr.csum_flags & M_CSUM_TCPv4)
|
||||
rtk_flags |= RTK_TDESC_CMD_TCPCSUM;
|
||||
if (m->m_pkthdr.csum_flags & M_CSUM_UDPv4)
|
||||
rtk_flags |= RTK_TDESC_CMD_UDPCSUM;
|
||||
}
|
||||
|
||||
map = sc->rtk_ldata.rtk_tx_dmamap[*idx];
|
||||
error = bus_dmamap_load_mbuf(sc->sc_dmat, map,
|
||||
m_head, BUS_DMA_NOWAIT);
|
||||
error = bus_dmamap_load_mbuf(sc->sc_dmat, map, m, BUS_DMA_NOWAIT);
|
||||
|
||||
if (error) {
|
||||
/* XXX try to defrag if EFBIG? */
|
||||
|
||||
aprint_error("%s: can't map mbuf (error %d)\n",
|
||||
sc->sc_dev.dv_xname, error);
|
||||
|
||||
if (error == EFBIG &&
|
||||
sc->rtk_ldata.rtk_tx_free == RTK_TX_DESC_CNT) {
|
||||
return error;
|
||||
}
|
||||
|
||||
return ENOBUFS;
|
||||
}
|
||||
|
||||
if (map->dm_nsegs > sc->rtk_ldata.rtk_tx_free - 4)
|
||||
return ENOBUFS;
|
||||
if (map->dm_nsegs > sc->rtk_ldata.rtk_tx_free - 4) {
|
||||
error = ENOBUFS;
|
||||
goto fail_unload;
|
||||
}
|
||||
/*
|
||||
* Map the segment array into descriptors. Note that we set the
|
||||
* start-of-frame and end-of-frame markers for either TX or RX, but
|
||||
@ -1539,8 +1561,16 @@ re_encap(struct rtk_softc *sc, struct mbuf *m_head, int *idx)
|
||||
curidx = *idx;
|
||||
while (1) {
|
||||
d = &sc->rtk_ldata.rtk_tx_list[curidx];
|
||||
if (le32toh(d->rtk_cmdstat) & RTK_RDESC_STAT_OWN)
|
||||
return ENOBUFS;
|
||||
if (le32toh(d->rtk_cmdstat) & RTK_RDESC_STAT_OWN) {
|
||||
while (i > 0) {
|
||||
sc->rtk_ldata.rtk_tx_list[
|
||||
(curidx + RTK_TX_DESC_CNT - i) %
|
||||
RTK_TX_DESC_CNT].rtk_cmdstat = 0;
|
||||
i--;
|
||||
}
|
||||
error = ENOBUFS;
|
||||
goto fail_unload;
|
||||
}
|
||||
|
||||
cmdstat = map->dm_segs[i].ds_len;
|
||||
d->rtk_bufaddr_lo =
|
||||
@ -1570,7 +1600,7 @@ re_encap(struct rtk_softc *sc, struct mbuf *m_head, int *idx)
|
||||
sc->rtk_ldata.rtk_tx_dmamap[*idx] =
|
||||
sc->rtk_ldata.rtk_tx_dmamap[curidx];
|
||||
sc->rtk_ldata.rtk_tx_dmamap[curidx] = map;
|
||||
sc->rtk_ldata.rtk_tx_mbuf[curidx] = m_head;
|
||||
sc->rtk_ldata.rtk_tx_mbuf[curidx] = m;
|
||||
sc->rtk_ldata.rtk_tx_free -= map->dm_nsegs;
|
||||
|
||||
/*
|
||||
@ -1579,7 +1609,7 @@ re_encap(struct rtk_softc *sc, struct mbuf *m_head, int *idx)
|
||||
* transmission attempt.
|
||||
*/
|
||||
|
||||
if ((mtag = VLAN_OUTPUT_TAG(&sc->ethercom, m_head)) != NULL) {
|
||||
if ((mtag = VLAN_OUTPUT_TAG(&sc->ethercom, m)) != NULL) {
|
||||
sc->rtk_ldata.rtk_tx_list[*idx].rtk_vlanctl =
|
||||
htole32(htons(VLAN_TAG_VALUE(mtag)) |
|
||||
RTK_TDESC_VLANCTL_TAG);
|
||||
@ -1597,6 +1627,11 @@ re_encap(struct rtk_softc *sc, struct mbuf *m_head, int *idx)
|
||||
*idx = curidx;
|
||||
|
||||
return 0;
|
||||
|
||||
fail_unload:
|
||||
bus_dmamap_unload(sc->sc_dmat, map);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1614,11 +1649,19 @@ re_start(struct ifnet *ifp)
|
||||
|
||||
idx = sc->rtk_ldata.rtk_tx_prodidx;
|
||||
while (sc->rtk_ldata.rtk_tx_mbuf[idx] == NULL) {
|
||||
int error;
|
||||
|
||||
IF_DEQUEUE(&ifp->if_snd, m_head);
|
||||
if (m_head == NULL)
|
||||
break;
|
||||
|
||||
if (re_encap(sc, m_head, &idx)) {
|
||||
error = re_encap(sc, m_head, &idx);
|
||||
if (error == EFBIG) {
|
||||
ifp->if_oerrors++;
|
||||
m_freem(m_head);
|
||||
continue;
|
||||
}
|
||||
if (error) {
|
||||
IF_PREPEND(&ifp->if_snd, m_head);
|
||||
ifp->if_flags |= IFF_OACTIVE;
|
||||
break;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: rtl81x9reg.h,v 1.10 2005/02/27 00:27:02 perry Exp $ */
|
||||
/* $NetBSD: rtl81x9reg.h,v 1.11 2005/03/12 08:01:51 yamt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997, 1998
|
||||
@ -465,6 +465,7 @@ struct rtk_desc {
|
||||
#define RTK_TDESC_CMD_UDPCSUM 0x00020000 /* UDP checksum enable */
|
||||
#define RTK_TDESC_CMD_IPCSUM 0x00040000 /* IP header checksum enable */
|
||||
#define RTK_TDESC_CMD_MSSVAL 0x07FF0000 /* Large send MSS value */
|
||||
#define RTK_TDESC_CMD_MSSVAL_SHIFT 16 /* Shift of the above */
|
||||
#define RTK_TDESC_CMD_LGSEND 0x08000000 /* TCP large send enb */
|
||||
#define RTK_TDESC_CMD_EOF 0x10000000 /* end of frame marker */
|
||||
#define RTK_TDESC_CMD_SOF 0x20000000 /* start of frame marker */
|
||||
@ -567,5 +568,3 @@ struct rtk_stats {
|
||||
|
||||
#define RTK_JUMBO_FRAMELEN 9018
|
||||
#define RTK_JUMBO_MTU (RTK_JUMBO_FRAMELEN-ETHER_HDR_LEN-ETHER_CRC_LEN)
|
||||
|
||||
#define RTK_NTXSEGS 32
|
||||
|
Loading…
Reference in New Issue
Block a user