diff options
author | Ryan Thomas McBride <mcbride@cvs.openbsd.org> | 2004-06-18 20:42:36 +0000 |
---|---|---|
committer | Ryan Thomas McBride <mcbride@cvs.openbsd.org> | 2004-06-18 20:42:36 +0000 |
commit | 60ef80006584c1170f8009ed0960d8c8723336c8 (patch) | |
tree | 9784e8f5d7cee17ecc76f87b65b2ce8de4616d40 /sys/dev/pci/if_em.c | |
parent | cf6b53ada53d65f3f3eeaa22906e6d45fea066ba (diff) |
On architectures which have strict alignment, shift the entire mbuf chain by
ETHER_ALIGN bytes when jumbo packets are enabled (mtu > ETHERMTU).
ok henric@ (slightly different diff)
Diffstat (limited to 'sys/dev/pci/if_em.c')
-rw-r--r-- | sys/dev/pci/if_em.c | 55 |
1 files changed, 52 insertions, 3 deletions
diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c index 7952f851c8e..33806a83f1d 100644 --- a/sys/dev/pci/if_em.c +++ b/sys/dev/pci/if_em.c @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ /*$FreeBSD: if_em.c,v 1.38 2004/03/17 17:50:31 njl Exp $*/ -/* $OpenBSD: if_em.c,v 1.22 2004/06/18 20:31:31 mcbride Exp $ */ +/* $OpenBSD: if_em.c,v 1.23 2004/06/18 20:42:34 mcbride Exp $ */ #include "bpfilter.h" #include "vlan.h" @@ -3161,8 +3161,57 @@ em_process_receive_interrupts(struct em_softc* sc, int count) /* Assign correct length to the current fragment */ mp->m_len = len; +#ifdef __STRICT_ALIGNMENT + /* + * The ethernet payload is not 32-bit aligned when + * Jumbo packets are enabled, so on architectures with + * strict alignment we need to shift the entire packet + * ETHER_ALIGN bytes. Ugh. + */ + if (ifp->if_mtu > ETHERMTU) { + unsigned char tmp_align_buf[ETHER_ALIGN]; + int tmp_align_buf_len = 0; + + if (prev_len_adj > sc->align_buf_len) + prev_len_adj -= sc->align_buf_len; + else + prev_len_adj = 0; + + if (mp->m_len > MCLBYTES - ETHER_ALIGN) { + bcopy(mp->m_data + + (MCLBYTES - ETHER_ALIGN), + &tmp_align_buf, + ETHER_ALIGN); + tmp_align_buf_len = mp->m_len - + (MCLBYTES - ETHER_ALIGN); + mp->m_len -= ETHER_ALIGN; + } + + if (mp->m_len) { + bcopy(mp->m_data, + mp->m_data + ETHER_ALIGN, + mp->m_len); + if (!sc->align_buf_len) + mp->m_data += ETHER_ALIGN; + } + + if (sc->align_buf_len) { + mp->m_len += sc->align_buf_len; + bcopy(&sc->align_buf, + mp->m_data, + sc->align_buf_len); + } + + if (tmp_align_buf_len) + bcopy(&tmp_align_buf, + &sc->align_buf, + tmp_align_buf_len); + sc->align_buf_len = tmp_align_buf_len; + } +#endif /* __STRICT_ALIGNMENT */ + if (sc->fmp == NULL) { - mp->m_pkthdr.len = len; + mp->m_pkthdr.len = mp->m_len; sc->fmp = mp; /* Store the first mbuf */ sc->lmp = mp; } else { @@ -3178,7 +3227,7 @@ em_process_receive_interrupts(struct em_softc* sc, int count) } sc->lmp->m_next = mp; sc->lmp = sc->lmp->m_next; - sc->fmp->m_pkthdr.len += len; + sc->fmp->m_pkthdr.len += mp->m_len; } if (eop) { |