git: 4352733e6398 - stable/15 - LinuxKPI: skbuff: implement __skb_linearize()

Bjoern A. Zeeb <[email protected]>
Newsgroups gmane.os.freebsd.devel.cvs.src
Message-ID <6a66a1fe.26e35.8efd35a__40922.258053773$1785111152$gmane$org@gitrepo.freebsd.org>
The branch stable/15 has been updated by bz:

URL: https://cgit.FreeBSD.org/src/commit/?id=4352733e639897d271e4246fe8f6203ac9c05ab0

commit 4352733e639897d271e4246fe8f6203ac9c05ab0
Author:     Bjoern A. Zeeb <[email protected]>
AuthorDate: 2026-02-03 22:13:24 +0000
Commit:     Bjoern A. Zeeb <[email protected]>
CommitDate: 2026-07-26 16:48:13 +0000

    LinuxKPI: skbuff: implement __skb_linearize()
    
    skb_linearize() is used by mt7921, mt7925, and in the general mt76 tx dma
    code. __skb_linearize() is used in the general iwlwifi TX code but given
    the way we currently create TX skbs in LinuxKPI 802.11 we never hit that
    case.
    
    Sponsored by:   The FreeBSD Foundation
    
    (cherry picked from commit 9de11cc26ab61d7f80e8af84dbc55d8cbd6f832d)
---
 sys/compat/linuxkpi/common/include/linux/skbuff.h |  6 +--
 sys/compat/linuxkpi/common/src/linux_skbuff.c     | 60 +++++++++++++++++++++++
 2 files changed, 63 insertions(+), 3 deletions(-)

diff --git a/sys/compat/linuxkpi/common/include/linux/skbuff.h b/sys/compat/linuxkpi/common/include/linux/skbuff.h
index a0724803e732..9434655fc9f4 100644
--- a/sys/compat/linuxkpi/common/include/linux/skbuff.h
+++ b/sys/compat/linuxkpi/common/include/linux/skbuff.h
@@ -209,6 +209,8 @@ void linuxkpi_kfree_skb(struct sk_buff *);
 
 struct sk_buff *linuxkpi_skb_copy(const struct sk_buff *, gfp_t);
 
+int lkpi___skb_linearize(struct sk_buff *);
+
 /* -------------------------------------------------------------------------- */
 
 static inline struct sk_buff *
@@ -978,9 +980,7 @@ skb_network_header(struct sk_buff *skb)
 static inline int
 __skb_linearize(struct sk_buff *skb)
 {
-	SKB_TRACE(skb);
-	SKB_TODO();
-	return (-ENXIO);
+	return (lkpi___skb_linearize(skb));
 }
 
 static inline int
diff --git a/sys/compat/linuxkpi/common/src/linux_skbuff.c b/sys/compat/linuxkpi/common/src/linux_skbuff.c
index abfb642ba708..a2aa601d594e 100644
--- a/sys/compat/linuxkpi/common/src/linux_skbuff.c
+++ b/sys/compat/linuxkpi/common/src/linux_skbuff.c
@@ -222,6 +222,66 @@ linuxkpi_skb_copy(const struct sk_buff *skb, gfp_t gfp)
 	return (new);
 }
 
+int
+lkpi___skb_linearize(struct sk_buff *skb)
+{
+	struct sk_buff *new;
+	struct skb_shared_info *shinfo;
+	uint16_t fragno, count;
+
+	SKB_TRACE(skb);
+	SKB_IMPROVE("Hack completely re-allocating and freeing; FIXME");
+	new = skb_copy(skb, GFP_NOWAIT);
+	if (new == NULL)
+		return (-ENOMEM);
+
+	/* Now need to swap head, data, tail, ... and free from old (and then new). */
+	shinfo = skb->shinfo;
+	for (count = fragno = 0;
+	    count < shinfo->nr_frags && fragno < nitems(shinfo->frags);
+	    fragno++) {
+
+		if (shinfo->frags[fragno].page != NULL) {
+			struct page *p;
+
+			p = shinfo->frags[fragno].page;
+			shinfo->frags[fragno].size = 0;
+			shinfo->frags[fragno].offset = 0;
+			shinfo->frags[fragno].page = NULL;
+			__free_page(p);
+			count++;
+		}
+	}
+
+	if ((skb->_flags & _SKB_FLAGS_SKBEXTFRAG) != 0) {
+		void *p;
+
+		p = skb->head;
+		skb_free_frag(p);
+		skb->head = NULL;
+		skb->_flags &= ~_SKB_FLAGS_SKBEXTFRAG;
+	}
+
+#ifdef	SKB_DMA32_MALLOC
+	if (__predict_false(linuxkpi_skb_memlimit != 0))
+		free(skb->head, M_LKPISKB);
+	else
+#endif
+	kfree(skb->head);
+
+	skb->head = new->head;
+	skb->data = new->data;
+	skb->tail = new->tail;
+	skb->end = new->end;
+	skb->len = new->len;
+	skb->data_len = new->data_len;
+	skb->truesize = new->truesize;
+
+	uma_zfree(skbzone, new);
+
+	return (0);
+}
+
 void
 linuxkpi_kfree_skb(struct sk_buff *skb)
 {
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.