summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2024-03-05 18:52:42 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2024-03-05 18:52:42 +0000
commit0c3b2f883849a5f84b34fa46dfa9fe81d18118d3 (patch)
treee7fb7fa576d13598314c6b4fd106790393ec8e82
parent32c17a5e07eabf2a2bd2593cc6ca0e012115501b (diff)
Revert m_defrag() mbuf alignment to IP header.
m_defrag() is intended as last resort to make DMA transfers to the hardware. Therefore page alingment is more important than IP header alignment. The reason, why the mbuf returned by m_defrag() was switched to IP header alingment, was that ether_extract_headers() failed in em(4) driver with TSO on sparc64. This has been fixed by using memcpy(). The alignment change in m_defrag() is too late in the 7.5 relaese process. It may affect several drivers on different architectures. Bus dmamap for ixl(4) on sun4v expects page alignment. Such alignment issues and TSO mbuf mapping for IOMMU need more thought. OK deraadt@
-rw-r--r--sys/kern/uipc_mbuf.c14
1 files changed, 6 insertions, 8 deletions
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index ec675a2333f..fc7b515c83f 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uipc_mbuf.c,v 1.289 2024/02/21 09:28:29 claudio Exp $ */
+/* $OpenBSD: uipc_mbuf.c,v 1.290 2024/03/05 18:52:41 bluhm Exp $ */
/* $NetBSD: uipc_mbuf.c,v 1.15.4.1 1996/06/13 17:11:44 cgd Exp $ */
/*
@@ -545,29 +545,27 @@ m_purge(struct mbuf *m)
* mbuf chain defragmenter. This function uses some evil tricks to defragment
* an mbuf chain into a single buffer without changing the mbuf pointer.
* This needs to know a lot of the mbuf internals to make this work.
+ * The resulting mbuf is not aligned to IP header to assist DMA transfers.
*/
int
m_defrag(struct mbuf *m, int how)
{
struct mbuf *m0;
- unsigned int adj;
if (m->m_next == NULL)
return (0);
KASSERT(m->m_flags & M_PKTHDR);
- adj = mtod(m, unsigned long) & (sizeof(long) - 1);
if ((m0 = m_gethdr(how, m->m_type)) == NULL)
return (ENOBUFS);
- if (m->m_pkthdr.len + adj > MHLEN) {
- MCLGETL(m0, how, m->m_pkthdr.len + adj);
+ if (m->m_pkthdr.len > MHLEN) {
+ MCLGETL(m0, how, m->m_pkthdr.len);
if (!(m0->m_flags & M_EXT)) {
m_free(m0);
return (ENOBUFS);
}
}
- m0->m_data += adj;
m_copydata(m, 0, m->m_pkthdr.len, mtod(m0, caddr_t));
m0->m_pkthdr.len = m0->m_len = m->m_pkthdr.len;
@@ -586,9 +584,9 @@ m_defrag(struct mbuf *m, int how)
memcpy(&m->m_ext, &m0->m_ext, sizeof(struct mbuf_ext));
MCLINITREFERENCE(m);
m->m_flags |= m0->m_flags & (M_EXT|M_EXTWR);
- m->m_data = m->m_ext.ext_buf + adj;
+ m->m_data = m->m_ext.ext_buf;
} else {
- m->m_data = m->m_pktdat + adj;
+ m->m_data = m->m_pktdat;
memcpy(m->m_data, m0->m_data, m0->m_len);
}
m->m_pkthdr.len = m->m_len = m0->m_len;