diff options
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/if_em.c | 55 | ||||
-rw-r--r-- | sys/dev/pci/if_em.h | 9 |
2 files changed, 60 insertions, 4 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) { diff --git a/sys/dev/pci/if_em.h b/sys/dev/pci/if_em.h index 2ca50df8bc9..a67cd1a199c 100644 --- a/sys/dev/pci/if_em.h +++ b/sys/dev/pci/if_em.h @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ /*$FreeBSD: if_em.h,v 1.24 2003/11/14 18:02:24 pdeuskar Exp $*/ -/* $OpenBSD: if_em.h,v 1.6 2004/05/19 11:37:00 brad Exp $ */ +/* $OpenBSD: if_em.h,v 1.7 2004/06/18 20:42:35 mcbride Exp $ */ #ifndef _EM_H_DEFINED_ #define _EM_H_DEFINED_ @@ -326,8 +326,15 @@ struct em_softc { struct timeout em_intr_enable; struct timeout timer_handle; struct timeout tx_fifo_timer_handle; + #endif /* __OpenBSD__ */ +#ifdef __STRICT_ALIGNMENT + /* Used for carrying forward alignment adjustments */ + unsigned char align_buf[ETHER_ALIGN]; /* tail of unaligned packet */ + u_int8_t align_buf_len; /* bytes in tail */ +#endif /* __STRICT_ALIGNMENT */ + /* Info about the board itself */ u_int32_t part_num; u_int8_t link_active; |