summaryrefslogtreecommitdiffstats
path: root/sys/pci/if_rl.c
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2003-08-13 22:39:21 +0000
committerwpaul <wpaul@FreeBSD.org>2003-08-13 22:39:21 +0000
commitcbd02f7c9f1e970bbdc3738491ace0eac5fbd61b (patch)
tree02507c8cbd157a2fc70b73311220034615ad3efd /sys/pci/if_rl.c
parent7945dbb7bd8e4ee97efa0e69f1beb58618e87ab9 (diff)
downloadFreeBSD-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/if_rl.c')
-rw-r--r--sys/pci/if_rl.c39
1 files changed, 22 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;
OpenPOWER on IntegriCloud