diff options
-rw-r--r-- | net/mac80211/mesh_hwmp.c | 32 |
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. */ | ||
209 | static 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 | */ |
213 | int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, | 239 | int 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 | ||