diff --git a/sys/compat/linuxkpi/common/include/linux/skbuff.h b/sys/compat/linuxkpi/common/include/linux/skbuff.h --- a/sys/compat/linuxkpi/common/include/linux/skbuff.h +++ b/sys/compat/linuxkpi/common/include/linux/skbuff.h @@ -145,7 +145,6 @@ }; struct list_head list; }; - uint32_t _alloc_len; /* Length of alloc data-buf. XXX-BZ give up for truesize? */ uint32_t len; /* ? */ uint32_t data_len; /* ? If we have frags? */ uint32_t truesize; /* The total size of all buffers, incl. frags. */ diff --git a/sys/compat/linuxkpi/common/src/linux_skbuff.c b/sys/compat/linuxkpi/common/src/linux_skbuff.c --- a/sys/compat/linuxkpi/common/src/linux_skbuff.c +++ b/sys/compat/linuxkpi/common/src/linux_skbuff.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2020-2022 The FreeBSD Foundation + * Copyright (c) 2020-2024 The FreeBSD Foundation * Copyright (c) 2021-2022 Bjoern A. Zeeb * * This software was developed by Björn Zeeb under sponsorship from @@ -63,7 +63,6 @@ &linuxkpi_debug_skb, 0, "SKB debug level"); #endif -#ifdef __LP64__ /* * Realtek wireless drivers (e.g., rtw88) require 32bit DMA in a single segment. * busdma(9) has a hard time providing this currently for 3-ish pages at large @@ -76,7 +75,6 @@ SYSCTL_INT(_compat_linuxkpi_skb, OID_AUTO, mem_limit, CTLFLAG_RDTUN, &linuxkpi_skb_memlimit, 0, "SKB memory limit: 0=no limit, " "1=32bit, 2=36bit, other=undef (currently 32bit)"); -#endif static MALLOC_DEFINE(M_LKPISKB, "lkpiskb", "Linux KPI skbuff compat"); @@ -87,14 +85,19 @@ size_t len; len = sizeof(*skb) + size + sizeof(struct skb_shared_info); + /* - * Using our own type here not backing my kmalloc. + * We need to use contigmalloc for everything which is a page or more. + * We also need to call contigmalloc in case the tunable is set. + * + * Historically we are using our own type here not backing by kmalloc. * We assume no one calls kfree directly on the skb. + * XXX-BZ this can change (for most of it) once kmalloc() etc. are + * fixed -- still having to think what to do with the TUNABLE->SYSCTL + * then. Will likely need a wrapper around __kmalloc() taking a "high" + * argument as well? */ -#ifdef __LP64__ - if (__predict_true(linuxkpi_skb_memlimit == 0)) { - skb = malloc(len, M_LKPISKB, linux_check_m_flags(gfp) | M_ZERO); - } else { + if (len >= PAGE_SIZE || __predict_false(linuxkpi_skb_memlimit != 0)) { vm_paddr_t high; switch (linuxkpi_skb_memlimit) { @@ -106,21 +109,19 @@ high = (0xffffffff); /* 1<<32 really. */ break; } - len = roundup_pow_of_two(len); + len = roundup(len, PAGE_SIZE); skb = contigmalloc(len, M_LKPISKB, linux_check_m_flags(gfp) | M_ZERO, 0, high, PAGE_SIZE, 0); + } else { + skb = malloc(len, M_LKPISKB, linux_check_m_flags(gfp) | M_ZERO); } -#else - skb = malloc(len, M_LKPISKB, linux_check_m_flags(gfp) | M_ZERO); -#endif + if (skb == NULL) return (skb); - skb->_alloc_len = len; skb->truesize = size; skb->head = skb->data = skb->tail = (uint8_t *)(skb+1); skb->end = skb->head + size; - skb->prev = skb->next = skb; skb->shinfo = (struct skb_shared_info *)(skb->end); @@ -258,14 +259,7 @@ skb_free_frag(p); } -#ifdef __LP64__ - if (__predict_true(linuxkpi_skb_memlimit == 0)) - free(skb, M_LKPISKB); - else - contigfree(skb, skb->_alloc_len, M_LKPISKB); -#else free(skb, M_LKPISKB); -#endif } #ifdef DDB @@ -284,9 +278,8 @@ db_printf("skb %p\n", skb); db_printf("\tnext %p prev %p\n", skb->next, skb->prev); db_printf("\tlist %p\n", &skb->list); - db_printf("\t_alloc_len %u len %u data_len %u truesize %u mac_len %u\n", - skb->_alloc_len, skb->len, skb->data_len, skb->truesize, - skb->mac_len); + db_printf("\tlen %u data_len %u truesize %u mac_len %u\n", + skb->len, skb->data_len, skb->truesize, skb->mac_len); db_printf("\tcsum %#06x l3hdroff %u l4hdroff %u priority %u qmap %u\n", skb->csum, skb->l3hdroff, skb->l4hdroff, skb->priority, skb->qmap); db_printf("\tpkt_type %d dev %p sk %p\n", @@ -298,6 +291,7 @@ skb->head, skb->data, skb->tail, skb->end); db_printf("\tshinfo %p m %p m_free_func %p\n", skb->shinfo, skb->m, skb->m_free_func); + /* Can we still print the allocation type malloc/contigmalloc and size? */ if (skb->shinfo != NULL) { struct skb_shared_info *shinfo;