diff options
author | wpaul <wpaul@FreeBSD.org> | 2003-08-13 22:39:21 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 2003-08-13 22:39:21 +0000 |
commit | cbd02f7c9f1e970bbdc3738491ace0eac5fbd61b (patch) | |
tree | 02507c8cbd157a2fc70b73311220034615ad3efd /sys/pci | |
parent | 7945dbb7bd8e4ee97efa0e69f1beb58618e87ab9 (diff) | |
download | FreeBSD-src-cbd02f7c9f1e970bbdc3738491ace0eac5fbd61b.zip FreeBSD-src-cbd02f7c9f1e970bbdc3738491ace0eac5fbd61b.tar.gz |
Set the TX hardware checksum offload bits on all the descriptors of a
multi-fragment transmission. I'm not sure if this is a bug or a requirement
that I overlooked with going through the documentation, but the sample
8169 NIC that I have seems to require it at least some of the time or
else it botches TCP checksums on segments that span multiple descriptors.
Diffstat (limited to 'sys/pci')
-rw-r--r-- | sys/pci/if_rl.c | 39 | ||||
-rw-r--r-- | sys/pci/if_rlreg.h | 1 |
2 files changed, 23 insertions, 17 deletions
diff --git a/sys/pci/if_rl.c b/sys/pci/if_rl.c index 130aba0..68cf049 100644 --- a/sys/pci/if_rl.c +++ b/sys/pci/if_rl.c @@ -1140,7 +1140,7 @@ rl_dma_map_desc(arg, segs, nseg, mapsize, error) cmdstat |= RL_TDESC_CMD_OWN; if (idx == (RL_RX_DESC_CNT - 1)) cmdstat |= RL_TDESC_CMD_EOR; - d->rl_cmdstat = htole32(cmdstat); + d->rl_cmdstat = htole32(cmdstat | ctx->rl_flags); i++; if (i == nseg) break; @@ -1716,6 +1716,7 @@ rl_newbuf (sc, idx, m) arg.sc = sc; arg.rl_idx = idx; arg.rl_maxsegs = 1; + arg.rl_flags = 0; arg.rl_ring = sc->rl_ldata.rl_rx_list; error = bus_dmamap_load_mbuf(sc->rl_ldata.rl_mtag, @@ -2373,12 +2374,27 @@ rl_encapcplus(sc, m_head, idx) struct rl_dmaload_arg arg; bus_dmamap_t map; int error; - u_int32_t csumcmd = RL_TDESC_CMD_OWN; struct m_tag *mtag; if (sc->rl_ldata.rl_tx_free < 4) return(EFBIG); + /* + * Set up checksum offload. Note: checksum offload bits must + * appear in all descriptors of a multi-descriptor transmit + * attempt. (This is according to testing done with an 8169 + * chip. I'm not sure if this is a requirement or a bug.) + */ + + arg.rl_flags = 0; + + if (m_head->m_pkthdr.csum_flags & CSUM_IP) + arg.rl_flags |= RL_TDESC_CMD_IPCSUM; + if (m_head->m_pkthdr.csum_flags & CSUM_TCP) + arg.rl_flags |= RL_TDESC_CMD_TCPCSUM; + if (m_head->m_pkthdr.csum_flags & CSUM_UDP) + arg.rl_flags |= RL_TDESC_CMD_UDPCSUM; + arg.sc = sc; arg.rl_idx = *idx; arg.rl_maxsegs = sc->rl_ldata.rl_tx_free; @@ -2439,24 +2455,13 @@ rl_encapcplus(sc, m_head, idx) sc->rl_ldata.rl_tx_list[*idx].rl_vlanctl = htole32(htons(VLAN_TAG_VALUE(mtag)) | RL_TDESC_VLANCTL_TAG); - /* - * Set up checksum offload. Note: checksum offload bits must - * appear in the first descriptor of a multi-descriptor - * transmission attempt. - */ - - if (m_head->m_pkthdr.csum_flags & CSUM_IP) - csumcmd |= RL_TDESC_CMD_IPCSUM; - if (m_head->m_pkthdr.csum_flags & CSUM_TCP) - csumcmd |= RL_TDESC_CMD_TCPCSUM; - if (m_head->m_pkthdr.csum_flags & CSUM_UDP) - csumcmd |= RL_TDESC_CMD_UDPCSUM; - /* Transfer ownership of packet to the chip. */ - sc->rl_ldata.rl_tx_list[arg.rl_idx].rl_cmdstat |= htole32(csumcmd); + sc->rl_ldata.rl_tx_list[arg.rl_idx].rl_cmdstat |= + htole32(RL_TDESC_CMD_OWN); if (*idx != arg.rl_idx) - sc->rl_ldata.rl_tx_list[*idx].rl_cmdstat |= htole32(csumcmd); + sc->rl_ldata.rl_tx_list[*idx].rl_cmdstat |= + htole32(RL_TDESC_CMD_OWN); RL_DESC_INC(arg.rl_idx); *idx = arg.rl_idx; diff --git a/sys/pci/if_rlreg.h b/sys/pci/if_rlreg.h index 4a32aef..5ca6368 100644 --- a/sys/pci/if_rlreg.h +++ b/sys/pci/if_rlreg.h @@ -602,6 +602,7 @@ struct rl_dmaload_arg { struct rl_softc *sc; int rl_idx; int rl_maxsegs; + u_int32_t rl_flags; struct rl_desc *rl_ring; }; |