1bcb41461efa044b0f49ef4c2dbb3cd9640b88cc
[openwrt/staging/neocturne.git] /
1 From: Felix Fietkau <nbd@nbd.name>
2 Date: Sat, 25 Jul 2020 20:53:23 +0200
3 Subject: [PATCH] mac80211: add a function for running rx without passing skbs
4 to the stack
5
6 This can be used to run mac80211 rx processing on a batch of frames in NAPI
7 poll before passing them to the network stack in a large batch.
8 This can improve icache footprint, or it can be used to pass frames via
9 netif_receive_skb_list.
10
11 Signed-off-by: Felix Fietkau <nbd@nbd.name>
12 ---
13
14 --- a/include/net/mac80211.h
15 +++ b/include/net/mac80211.h
16 @@ -4358,6 +4358,31 @@ void ieee80211_free_hw(struct ieee80211_
17 void ieee80211_restart_hw(struct ieee80211_hw *hw);
18
19 /**
20 + * ieee80211_rx_list - receive frame and store processed skbs in a list
21 + *
22 + * Use this function to hand received frames to mac80211. The receive
23 + * buffer in @skb must start with an IEEE 802.11 header. In case of a
24 + * paged @skb is used, the driver is recommended to put the ieee80211
25 + * header of the frame on the linear part of the @skb to avoid memory
26 + * allocation and/or memcpy by the stack.
27 + *
28 + * This function may not be called in IRQ context. Calls to this function
29 + * for a single hardware must be synchronized against each other. Calls to
30 + * this function, ieee80211_rx_ni() and ieee80211_rx_irqsafe() may not be
31 + * mixed for a single hardware. Must not run concurrently with
32 + * ieee80211_tx_status() or ieee80211_tx_status_ni().
33 + *
34 + * This function must be called with BHs disabled and RCU read lock
35 + *
36 + * @hw: the hardware this frame came in on
37 + * @sta: the station the frame was received from, or %NULL
38 + * @skb: the buffer to receive, owned by mac80211 after this call
39 + * @list: the destination list
40 + */
41 +void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
42 + struct sk_buff *skb, struct list_head *list);
43 +
44 +/**
45 * ieee80211_rx_napi - receive frame from NAPI context
46 *
47 * Use this function to hand received frames to mac80211. The receive
48 --- a/net/mac80211/ieee80211_i.h
49 +++ b/net/mac80211/ieee80211_i.h
50 @@ -218,7 +218,7 @@ enum ieee80211_rx_flags {
51 };
52
53 struct ieee80211_rx_data {
54 - struct napi_struct *napi;
55 + struct list_head *list;
56 struct sk_buff *skb;
57 struct ieee80211_local *local;
58 struct ieee80211_sub_if_data *sdata;
59 --- a/net/mac80211/rx.c
60 +++ b/net/mac80211/rx.c
61 @@ -2578,8 +2578,8 @@ static void ieee80211_deliver_skb_to_loc
62 memset(skb->cb, 0, sizeof(skb->cb));
63
64 /* deliver to local stack */
65 - if (rx->napi)
66 - napi_gro_receive(rx->napi, skb);
67 + if (rx->list)
68 + list_add_tail(&skb->list, rx->list);
69 else
70 netif_receive_skb(skb);
71 }
72 @@ -3869,7 +3869,6 @@ void ieee80211_release_reorder_timeout(s
73 /* This is OK -- must be QoS data frame */
74 .security_idx = tid,
75 .seqno_idx = tid,
76 - .napi = NULL, /* must be NULL to not have races */
77 };
78 struct tid_ampdu_rx *tid_agg_rx;
79
80 @@ -4479,8 +4478,8 @@ static bool ieee80211_invoke_fast_rx(str
81 /* deliver to local stack */
82 skb->protocol = eth_type_trans(skb, fast_rx->dev);
83 memset(skb->cb, 0, sizeof(skb->cb));
84 - if (rx->napi)
85 - napi_gro_receive(rx->napi, skb);
86 + if (rx->list)
87 + list_add_tail(&skb->list, rx->list);
88 else
89 netif_receive_skb(skb);
90
91 @@ -4547,7 +4546,7 @@ static bool ieee80211_prepare_and_rx_han
92 static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
93 struct ieee80211_sta *pubsta,
94 struct sk_buff *skb,
95 - struct napi_struct *napi)
96 + struct list_head *list)
97 {
98 struct ieee80211_local *local = hw_to_local(hw);
99 struct ieee80211_sub_if_data *sdata;
100 @@ -4562,7 +4561,7 @@ static void __ieee80211_rx_handle_packet
101 memset(&rx, 0, sizeof(rx));
102 rx.skb = skb;
103 rx.local = local;
104 - rx.napi = napi;
105 + rx.list = list;
106
107 if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
108 I802_DEBUG_INC(local->dot11ReceivedFragmentCount);
109 @@ -4670,8 +4669,8 @@ static void __ieee80211_rx_handle_packet
110 * This is the receive path handler. It is called by a low level driver when an
111 * 802.11 MPDU is received from the hardware.
112 */
113 -void ieee80211_rx_napi(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,
114 - struct sk_buff *skb, struct napi_struct *napi)
115 +void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,
116 + struct sk_buff *skb, struct list_head *list)
117 {
118 struct ieee80211_local *local = hw_to_local(hw);
119 struct ieee80211_rate *rate = NULL;
120 @@ -4763,36 +4762,53 @@ void ieee80211_rx_napi(struct ieee80211_
121 status->rx_flags = 0;
122
123 /*
124 - * key references and virtual interfaces are protected using RCU
125 - * and this requires that we are in a read-side RCU section during
126 - * receive processing
127 - */
128 - rcu_read_lock();
129 -
130 - /*
131 * Frames with failed FCS/PLCP checksum are not returned,
132 * all other frames are returned without radiotap header
133 * if it was previously present.
134 * Also, frames with less than 16 bytes are dropped.
135 */
136 skb = ieee80211_rx_monitor(local, skb, rate);
137 - if (!skb) {
138 - rcu_read_unlock();
139 + if (!skb)
140 return;
141 - }
142
143 ieee80211_tpt_led_trig_rx(local,
144 ((struct ieee80211_hdr *)skb->data)->frame_control,
145 skb->len);
146
147 - __ieee80211_rx_handle_packet(hw, pubsta, skb, napi);
148 -
149 - rcu_read_unlock();
150 + __ieee80211_rx_handle_packet(hw, pubsta, skb, list);
151
152 return;
153 drop:
154 kfree_skb(skb);
155 }
156 +EXPORT_SYMBOL(ieee80211_rx_list);
157 +
158 +void ieee80211_rx_napi(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,
159 + struct sk_buff *skb, struct napi_struct *napi)
160 +{
161 + struct sk_buff *tmp;
162 + LIST_HEAD(list);
163 +
164 +
165 + /*
166 + * key references and virtual interfaces are protected using RCU
167 + * and this requires that we are in a read-side RCU section during
168 + * receive processing
169 + */
170 + rcu_read_lock();
171 + ieee80211_rx_list(hw, pubsta, skb, &list);
172 + rcu_read_unlock();
173 +
174 + if (!napi) {
175 + netif_receive_skb_list(&list);
176 + return;
177 + }
178 +
179 + list_for_each_entry_safe(skb, tmp, &list, list) {
180 + skb_list_del_init(skb);
181 + napi_gro_receive(napi, skb);
182 + }
183 +}
184 EXPORT_SYMBOL(ieee80211_rx_napi);
185
186 /* This is a version of the rx handler that can be called from hard irq