aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPyun YongHyeon <yongari@FreeBSD.org>2006-05-21 23:45:56 +0000
committerPyun YongHyeon <yongari@FreeBSD.org>2006-05-21 23:45:56 +0000
commit2d3fe1bf18b593b15d5bb9a83ebbce3839cebc3a (patch)
treed38383fc6aeef1592306de9718912dc875b324b0
parent199a4ca5164c169329e66ebee6f05b9e67c3ffb7 (diff)
downloadsrc-2d3fe1bf18b593b15d5bb9a83ebbce3839cebc3a.tar.gz
src-2d3fe1bf18b593b15d5bb9a83ebbce3839cebc3a.zip
MFC if_em.c, 1.92 to RELENG_5_5:
Add jumbo frame support for architectures with strict alignment. Requested by: wilko Approved by: re (kensmith)
Notes
Notes: svn path=/releng/5.5/; revision=158805
-rw-r--r--sys/dev/em/if_em.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/sys/dev/em/if_em.c b/sys/dev/em/if_em.c
index 3848ad54f0e5..785bc25db7e5 100644
--- a/sys/dev/em/if_em.c
+++ b/sys/dev/em/if_em.c
@@ -148,6 +148,9 @@ static void em_clean_transmit_interrupts(struct adapter *);
static int em_allocate_receive_structures(struct adapter *);
static int em_allocate_transmit_structures(struct adapter *);
static void em_process_receive_interrupts(struct adapter *, int);
+#ifndef __NO_STRICT_ALIGNMENT
+static int em_fixup_rx(struct adapter *);
+#endif
static void em_receive_checksum(struct adapter *,
struct em_rx_desc *,
struct mbuf *);
@@ -2839,11 +2842,20 @@ em_process_receive_interrupts(struct adapter * adapter, int count)
ifp->if_ipackets++;
em_receive_checksum(adapter, current_desc,
adapter->fmp);
+#ifndef __NO_STRICT_ALIGNMENT
+ if (ifp->if_mtu > ETHERMTU &&
+ em_fixup_rx(adapter) != 0)
+ goto skip;
+
+#endif
if (current_desc->status & E1000_RXD_STAT_VP)
VLAN_INPUT_TAG(ifp, adapter->fmp,
(current_desc->special &
E1000_RXD_SPC_VLAN_MASK),
adapter->fmp = NULL);
+#ifndef __NO_STRICT_ALIGNMENT
+skip:
+#endif
m = adapter->fmp;
adapter->fmp = NULL;
adapter->lmp = NULL;
@@ -2879,6 +2891,54 @@ em_process_receive_interrupts(struct adapter * adapter, int count)
return;
}
+#ifndef __NO_STRICT_ALIGNMENT
+/*
+ * When jumbo frames are enabled we should realign entire payload on
+ * architecures with strict alignment. This is serious design mistake of 8254x
+ * as it nullifies DMA operations. 8254x just allows RX buffer size to be
+ * 2048/4096/8192/16384. What we really want is 2048 - ETHER_ALIGN to align its
+ * payload. On architecures without strict alignment restrictions 8254x still
+ * performs unaligned memory access which would reduce the performance too.
+ * To avoid copying over an entire frame to align, we allocate a new mbuf and
+ * copy ethernet header to the new mbuf. The new mbuf is prepended into the
+ * existing mbuf chain.
+ *
+ * Be aware, best performance of the 8254x is achived only when jumbo frame is
+ * not used at all on architectures with strict alignment.
+ */
+static int
+em_fixup_rx(struct adapter *adapter)
+{
+ struct mbuf *m, *n;
+ int error;
+
+ error = 0;
+ m = adapter->fmp;
+ if (m->m_len <= (MCLBYTES - ETHER_HDR_LEN)) {
+ bcopy(m->m_data, m->m_data + ETHER_HDR_LEN, m->m_len);
+ m->m_data += ETHER_HDR_LEN;
+ } else {
+ MGETHDR(n, M_DONTWAIT, MT_DATA);
+ if (n != NULL) {
+ bcopy(m->m_data, n->m_data, ETHER_HDR_LEN);
+ m->m_data += ETHER_HDR_LEN;
+ m->m_len -= ETHER_HDR_LEN;
+ n->m_len = ETHER_HDR_LEN;
+ M_MOVE_PKTHDR(n, m);
+ n->m_next = m;
+ adapter->fmp = n;
+ } else {
+ adapter->dropped_pkts++;
+ m_freem(adapter->fmp);
+ adapter->fmp = NULL;
+ error = ENOMEM;
+ }
+ }
+
+ return (error);
+}
+#endif
+
/*********************************************************************
*
* Verify that the hardware indicated that the checksum is valid.