Page MenuHomeFreeBSD

D48474.id.diff
No OneTemporary

D48474.id.diff

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
@@ -706,6 +706,8 @@
SKB_TRACE(q);
while ((skb = __skb_dequeue(q)) != NULL)
kfree_skb(skb);
+ WARN_ONCE(skb_queue_len(q) != 0, "%s: queue %p not empty: %u",
+ __func__, q, skb_queue_len(q));
}
static inline void
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -3815,7 +3815,20 @@
*/
skb = dev_alloc_skb(hw->extra_tx_headroom + m->m_pkthdr.len);
if (skb == NULL) {
- ic_printf(ic, "ERROR %s: skb alloc failed\n", __func__);
+ static uint8_t skb_alloc_failures = 0;
+
+ if (skb_alloc_failures++ == 0) {
+ int tid;
+
+ sta = LSTA_TO_STA(lsta);
+ ic_printf(ic, "ERROR %s: skb alloc failed %d + %d, lsta %p sta %p ni %p\n",
+ __func__, hw->extra_tx_headroom, m->m_pkthdr.len, lsta, sta, ni);
+ for (tid = 0; tid < nitems(sta->txq); tid++) {
+ ltxq = TXQ_TO_LTXQ(sta->txq[tid]);
+ ic_printf(ic, " tid %d ltxq %p seen_dequeue %d stopped %d skb_queue_len %u\n",
+ tid, ltxq, ltxq->seen_dequeue, ltxq-> stopped, skb_queue_len(&ltxq->skbq));
+ }
+ }
ieee80211_free_node(ni);
m_freem(m);
return;
diff --git a/sys/contrib/dev/rtw88/main.h b/sys/contrib/dev/rtw88/main.h
--- a/sys/contrib/dev/rtw88/main.h
+++ b/sys/contrib/dev/rtw88/main.h
@@ -735,6 +735,9 @@
struct sk_buff_head queue;
atomic_t sn;
struct timer_list purge_timer;
+#if defined(__FreeBSD__)
+ int firstqtime;
+#endif
};
struct rtw_ra_report {
diff --git a/sys/contrib/dev/rtw88/tx.c b/sys/contrib/dev/rtw88/tx.c
--- a/sys/contrib/dev/rtw88/tx.c
+++ b/sys/contrib/dev/rtw88/tx.c
@@ -192,7 +192,25 @@
spin_lock_irqsave(&tx_report->q_lock, flags);
qlen = skb_queue_len(&tx_report->queue);
if (qlen > 0)
+#if defined(__linux__)
skb_queue_purge(&tx_report->queue);
+#elif defined(__FreeBSD__)
+ {
+ struct sk_buff *skb;
+
+ /*
+ * We only free too old entries; all the others still have
+ * a chance to be picked up by rtw_tx_report_handle().
+ */
+ while ((skb = __skb_dequeue(&tx_report->queue)) != NULL &&
+ time_after(tx_report->firstqtime + RTW_TX_PROBE_TIMEOUT, skb->ip_summed))
+ kfree_skb(skb);
+
+ }
+ /* Reset the firstqtime so any next packets modifies the timer. */
+ tx_report->firstqtime = 0;
+#endif
+
spin_unlock_irqrestore(&tx_report->q_lock, flags);
/*
@@ -212,6 +230,9 @@
struct rtw_tx_report *tx_report = &rtwdev->tx_report;
unsigned long flags;
u8 *drv_data;
+#if defined(__FreeBSD__)
+ uint32_t qlen;
+#endif
/* pass sn to tx report handler through driver data */
drv_data = (u8 *)IEEE80211_SKB_CB(skb)->status.status_driver_data;
@@ -219,9 +240,33 @@
spin_lock_irqsave(&tx_report->q_lock, flags);
__skb_queue_tail(&tx_report->queue, skb);
+#if defined(__linux__)
spin_unlock_irqrestore(&tx_report->q_lock, flags);
mod_timer(&tx_report->purge_timer, jiffies + RTW_TX_PROBE_TIMEOUT);
+#elif defined(__FreeBSD__)
+ /*
+ * ip_summed is unused in rtw88 so abuse it to test if this helps
+ * finding / preventing the skb leak; this is possible in
+ * FreeBSD at the moment as both the field and jiffies are int.
+ */
+ skb->ip_summed = jiffies;
+
+ /*
+ * Initialize the first time (after the queue is emopty).
+ * rtw_tx_report_purge_timer() will update the "firstqtime"
+ * whenever it finishes clearing the expired entries.
+ * Should get us into a rolling cleanup and never possibly
+ * queue endlessly.
+ */
+ qlen = skb_queue_len(&tx_report->queue);
+ if (qlen == 1 || tx_report->firstqtime == 0)
+ tx_report->firstqtime = jiffies;
+ spin_unlock_irqrestore(&tx_report->q_lock, flags);
+
+ if (time_before(jiffies, tx_report->firstqtime + RTW_TX_PROBE_TIMEOUT))
+ mod_timer(&tx_report->purge_timer, jiffies + RTW_TX_PROBE_TIMEOUT);
+#endif
}
EXPORT_SYMBOL(rtw_tx_report_enqueue);

File Metadata

Mime Type
text/plain
Expires
Sat, Jan 18, 10:02 AM (1 h, 3 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15830111
Default Alt Text
D48474.id.diff (3 KB)

Event Timeline