]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: mac80211: fold tid_ampdu_rx allocations into a flexible array
authorRosen Penev <rosenp@gmail.com>
Fri, 5 Jun 2026 00:56:27 +0000 (17:56 -0700)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 5 Jun 2026 07:59:30 +0000 (09:59 +0200)
Convert the separately-allocated reorder_buf pointer to a C99 flexible
array member at the end of struct tid_ampdu_rx, with both the
sk_buff_head and the jiffies timestamp in each array element. This
collapses three allocations into one and removes the corresponding
kfree() pairs from the error and free paths.

Assisted-by: opencode:big-pickle
Signed-off-by: Rosen Penev <rosenp@gmail.com>
Link: https://patch.msgid.link/20260605005627.317194-1-rosenp@gmail.com
[fix kernel-doc]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/agg-rx.c
net/mac80211/rx.c
net/mac80211/sta_info.h

index 0140ac826b23aecda1198a619719826b76b77efd..9629e00069a1f3e3630d79d6d0a6e5dd126c9135 100644 (file)
@@ -49,9 +49,7 @@ static void ieee80211_free_tid_rx(struct rcu_head *h)
        int i;
 
        for (i = 0; i < tid_rx->buf_size; i++)
-               __skb_queue_purge(&tid_rx->reorder_buf[i]);
-       kfree(tid_rx->reorder_buf);
-       kfree(tid_rx->reorder_time);
+               __skb_queue_purge(&tid_rx->reorder[i].buf);
        kfree(tid_rx);
 }
 
@@ -412,7 +410,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
        }
 
        /* prepare A-MPDU MLME for Rx aggregation */
-       tid_agg_rx = kzalloc_obj(*tid_agg_rx);
+       tid_agg_rx = kzalloc_flex(*tid_agg_rx, reorder, buf_size);
        if (!tid_agg_rx)
                goto end;
 
@@ -426,27 +424,13 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
        timer_setup(&tid_agg_rx->reorder_timer,
                    sta_rx_agg_reorder_timer_expired, 0);
 
-       /* prepare reordering buffer */
-       tid_agg_rx->reorder_buf =
-               kzalloc_objs(struct sk_buff_head, buf_size);
-       tid_agg_rx->reorder_time =
-               kcalloc(buf_size, sizeof(unsigned long), GFP_KERNEL);
-       if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) {
-               kfree(tid_agg_rx->reorder_buf);
-               kfree(tid_agg_rx->reorder_time);
-               kfree(tid_agg_rx);
-               goto end;
-       }
-
        for (i = 0; i < buf_size; i++)
-               __skb_queue_head_init(&tid_agg_rx->reorder_buf[i]);
+               __skb_queue_head_init(&tid_agg_rx->reorder[i].buf);
 
        ret = drv_ampdu_action(local, sta->sdata, &params);
        ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n",
               sta->sta.addr, tid, ret);
        if (ret) {
-               kfree(tid_agg_rx->reorder_buf);
-               kfree(tid_agg_rx->reorder_time);
                kfree(tid_agg_rx);
                goto end;
        }
index db421edfd54c40eb58319e4067ca5d1d14c82ca4..fb9a3574afe99d888cc706696f3ac3138550d61b 100644 (file)
@@ -1188,7 +1188,7 @@ static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
 static inline bool ieee80211_rx_reorder_ready(struct tid_ampdu_rx *tid_agg_rx,
                                              int index)
 {
-       struct sk_buff_head *frames = &tid_agg_rx->reorder_buf[index];
+       struct sk_buff_head *frames = &tid_agg_rx->reorder[index].buf;
        struct sk_buff *tail = skb_peek_tail(frames);
        struct ieee80211_rx_status *status;
 
@@ -1211,7 +1211,7 @@ static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata,
                                            int index,
                                            struct sk_buff_head *frames)
 {
-       struct sk_buff_head *skb_list = &tid_agg_rx->reorder_buf[index];
+       struct sk_buff_head *skb_list = &tid_agg_rx->reorder[index].buf;
        struct sk_buff *skb;
        struct ieee80211_rx_status *status;
 
@@ -1290,14 +1290,14 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,
                                continue;
                        }
                        if (skipped &&
-                           !time_after(jiffies, tid_agg_rx->reorder_time[j] +
+                           !time_after(jiffies, tid_agg_rx->reorder[j].time +
                                        HT_RX_REORDER_BUF_TIMEOUT))
                                goto set_release_timer;
 
                        /* don't leave incomplete A-MSDUs around */
                        for (i = (index + 1) % tid_agg_rx->buf_size; i != j;
                             i = (i + 1) % tid_agg_rx->buf_size)
-                               __skb_queue_purge(&tid_agg_rx->reorder_buf[i]);
+                               __skb_queue_purge(&tid_agg_rx->reorder[i].buf);
 
                        ht_dbg_ratelimited(sdata,
                                           "release an RX reorder frame due to timeout on earlier frames\n");
@@ -1331,7 +1331,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,
 
                if (!tid_agg_rx->removed)
                        mod_timer(&tid_agg_rx->reorder_timer,
-                                 tid_agg_rx->reorder_time[j] + 1 +
+                                 tid_agg_rx->reorder[j].time + 1 +
                                  HT_RX_REORDER_BUF_TIMEOUT);
        } else {
                timer_delete(&tid_agg_rx->reorder_timer);
@@ -1426,9 +1426,9 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata
        }
 
        /* put the frame in the reordering buffer */
-       __skb_queue_tail(&tid_agg_rx->reorder_buf[index], skb);
+       __skb_queue_tail(&tid_agg_rx->reorder[index].buf, skb);
        if (!(status->flag & RX_FLAG_AMSDU_MORE)) {
-               tid_agg_rx->reorder_time[index] = jiffies;
+               tid_agg_rx->reorder[index].time = jiffies;
                tid_agg_rx->stored_mpdu_num++;
                ieee80211_sta_reorder_release(sdata, tid_agg_rx, frames);
        }
index 26138934b72e78e510b2a6fd61727c7a79924972..5da3142d8516ef6f9f8e109094359dbf6720f61e 100644 (file)
@@ -207,11 +207,8 @@ struct tid_ampdu_tx {
 /**
  * struct tid_ampdu_rx - TID aggregation information (Rx).
  *
- * @reorder_buf: buffer to reorder incoming aggregated MPDUs. An MPDU may be an
- *     A-MSDU with individually reported subframes.
  * @reorder_buf_filtered: bitmap indicating where there are filtered frames in
  *     the reorder buffer that should be ignored when releasing frames
- * @reorder_time: jiffies when skb was added
  * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value)
  * @reorder_timer: releases expired frames from the reorder buffer.
  * @sta: station we are attached to
@@ -228,6 +225,10 @@ struct tid_ampdu_tx {
  *     and ssn.
  * @removed: this session is removed (but might have been found due to RCU)
  * @started: this session has started (head ssn or higher was received)
+ * @reorder: reorder buffer entries
+ * @reorder.buf: &struct sk_buff_head for the frames, since there could be
+ *     multiple at each entry from an A-MSDU reported as individual subframes
+ * @reorder.time: time when this entry was filled (jiffies)
  *
  * This structure's lifetime is managed by RCU, assignments to
  * the array holding it must hold the aggregation mutex.
@@ -241,8 +242,6 @@ struct tid_ampdu_rx {
        struct rcu_head rcu_head;
        spinlock_t reorder_lock;
        u64 reorder_buf_filtered;
-       struct sk_buff_head *reorder_buf;
-       unsigned long *reorder_time;
        struct sta_info *sta;
        struct timer_list session_timer;
        struct timer_list reorder_timer;
@@ -256,6 +255,10 @@ struct tid_ampdu_rx {
        u8 auto_seq:1,
           removed:1,
           started:1;
+       struct {
+               struct sk_buff_head buf;
+               unsigned long time;
+       } reorder[];
 };
 
 /**