git: 9de11cc26ab6 - main - LinuxKPI: skbuff: implement __skb_linearize()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 17 Jul 2026 15:49:24 UTC
The branch main has been updated by bz:
URL: https://cgit.FreeBSD.org/src/commit/?id=9de11cc26ab61d7f80e8af84dbc55d8cbd6f832d
commit 9de11cc26ab61d7f80e8af84dbc55d8cbd6f832d
Author: Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2026-02-03 22:13:24 +0000
Commit: Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2026-07-17 15:48:53 +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
MFC after: 3 days
---
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)
{