aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/mesh_hwmp.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index fd4f76a3e139..63df0bc3dba4 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -8,6 +8,7 @@
8 */ 8 */
9 9
10#include <linux/slab.h> 10#include <linux/slab.h>
11#include "wme.h"
11#include "mesh.h" 12#include "mesh.h"
12 13
13#ifdef CONFIG_MAC80211_VERBOSE_MHWMP_DEBUG 14#ifdef CONFIG_MAC80211_VERBOSE_MHWMP_DEBUG
@@ -202,6 +203,27 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
202 return 0; 203 return 0;
203} 204}
204 205
206
207/* Headroom is not adjusted. Caller should ensure that skb has sufficient
208 * headroom in case the frame is encrypted. */
209static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata,
210 struct sk_buff *skb)
211{
212 struct ieee80211_local *local = sdata->local;
213 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
214
215 skb_set_mac_header(skb, 0);
216 skb_set_network_header(skb, 0);
217 skb_set_transport_header(skb, 0);
218
219 /* Send all internal mgmt frames on VO. Accordingly set TID to 7. */
220 skb_set_queue_mapping(skb, IEEE80211_AC_VO);
221 skb->priority = 7;
222
223 info->control.vif = &sdata->vif;
224 ieee80211_set_qos_hdr(local, skb);
225}
226
205/** 227/**
206 * mesh_send_path error - Sends a PERR mesh management frame 228 * mesh_send_path error - Sends a PERR mesh management frame
207 * 229 *
@@ -209,6 +231,10 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
209 * @target_sn: SN of the broken destination 231 * @target_sn: SN of the broken destination
210 * @target_rcode: reason code for this PERR 232 * @target_rcode: reason code for this PERR
211 * @ra: node this frame is addressed to 233 * @ra: node this frame is addressed to
234 *
235 * Note: This function may be called with driver locks taken that the driver
236 * also acquires in the TX path. To avoid a deadlock we don't transmit the
237 * frame directly but add it to the pending queue instead.
212 */ 238 */
213int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, 239int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
214 __le16 target_rcode, const u8 *ra, 240 __le16 target_rcode, const u8 *ra,
@@ -222,7 +248,7 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
222 248
223 if (!skb) 249 if (!skb)
224 return -1; 250 return -1;
225 skb_reserve(skb, local->hw.extra_tx_headroom); 251 skb_reserve(skb, local->tx_headroom + local->hw.extra_tx_headroom);
226 /* 25 is the size of the common mgmt part (24) plus the size of the 252 /* 25 is the size of the common mgmt part (24) plus the size of the
227 * common action part (1) 253 * common action part (1)
228 */ 254 */
@@ -263,7 +289,9 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
263 pos += 4; 289 pos += 4;
264 memcpy(pos, &target_rcode, 2); 290 memcpy(pos, &target_rcode, 2);
265 291
266 ieee80211_tx_skb(sdata, skb); 292 /* see note in function header */
293 prepare_frame_for_deferred_tx(sdata, skb);
294 ieee80211_add_pending_skb(local, skb);
267 return 0; 295 return 0;
268} 296}
269 297