aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mesh_hwmp.c
diff options
context:
space:
mode:
authorJavier Cardona <javier@cozybit.com>2011-09-06 15:10:43 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-09-13 15:42:29 -0400
commit2cca397f76a4a48ac20c34ec1e35bac8c6b08d1c (patch)
tree1392af2343bbfdc0e54fc9b20d62b631102a545c /net/mac80211/mesh_hwmp.c
parent2fa8b6a0e42570690a48a56cb65778211e3cc9cc (diff)
mac80211: Defer tranmission of mesh path errors
Under failure conditions, the mesh stack sends PERR messages to the previous sender of the failed frame. This happens in the tx feedback path, in which the transmission queue lock may be taken. Avoid a deadlock by sending the path error via the pending queue. Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/mesh_hwmp.c')
-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