mac80211: implement uAPSD
[pandora-kernel.git] / net / mac80211 / mesh_plink.c
1 /*
2  * Copyright (c) 2008, 2009 open80211s Ltd.
3  * Author:     Luis Carlos Cobo <luisca@cozybit.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  */
9 #include <linux/gfp.h>
10 #include <linux/kernel.h>
11 #include <linux/random.h>
12 #include "ieee80211_i.h"
13 #include "rate.h"
14 #include "mesh.h"
15
16 #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
17 #define mpl_dbg(fmt, args...)   printk(KERN_DEBUG fmt, ##args)
18 #else
19 #define mpl_dbg(fmt, args...)   do { (void)(0); } while (0)
20 #endif
21
22 #define PLINK_GET_LLID(p) (p + 2)
23 #define PLINK_GET_PLID(p) (p + 4)
24
25 #define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \
26                                 jiffies + HZ * t / 1000))
27
28 #define dot11MeshMaxRetries(s) (s->u.mesh.mshcfg.dot11MeshMaxRetries)
29 #define dot11MeshRetryTimeout(s) (s->u.mesh.mshcfg.dot11MeshRetryTimeout)
30 #define dot11MeshConfirmTimeout(s) (s->u.mesh.mshcfg.dot11MeshConfirmTimeout)
31 #define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout)
32 #define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks)
33
34 enum plink_event {
35         PLINK_UNDEFINED,
36         OPN_ACPT,
37         OPN_RJCT,
38         OPN_IGNR,
39         CNF_ACPT,
40         CNF_RJCT,
41         CNF_IGNR,
42         CLS_ACPT,
43         CLS_IGNR
44 };
45
46 static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
47                 enum ieee80211_self_protected_actioncode action,
48                 u8 *da, __le16 llid, __le16 plid, __le16 reason);
49
50 static inline
51 void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
52 {
53         atomic_inc(&sdata->u.mesh.mshstats.estab_plinks);
54         mesh_accept_plinks_update(sdata);
55 }
56
57 static inline
58 void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
59 {
60         atomic_dec(&sdata->u.mesh.mshstats.estab_plinks);
61         mesh_accept_plinks_update(sdata);
62 }
63
64 /**
65  * mesh_plink_fsm_restart - restart a mesh peer link finite state machine
66  *
67  * @sta: mesh peer link to restart
68  *
69  * Locking: this function must be called holding sta->lock
70  */
71 static inline void mesh_plink_fsm_restart(struct sta_info *sta)
72 {
73         sta->plink_state = NL80211_PLINK_LISTEN;
74         sta->llid = sta->plid = sta->reason = 0;
75         sta->plink_retries = 0;
76 }
77
78 /*
79  * NOTE: This is just an alias for sta_info_alloc(), see notes
80  *       on it in the lifecycle management section!
81  */
82 static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
83                                          u8 *hw_addr, u32 rates)
84 {
85         struct ieee80211_local *local = sdata->local;
86         struct sta_info *sta;
87
88         if (local->num_sta >= MESH_MAX_PLINKS)
89                 return NULL;
90
91         sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL);
92         if (!sta)
93                 return NULL;
94
95         sta->flags = WLAN_STA_AUTHORIZED | WLAN_STA_AUTH | WLAN_STA_WME;
96         sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
97         rate_control_rate_init(sta);
98
99         return sta;
100 }
101
102 /**
103  * __mesh_plink_deactivate - deactivate mesh peer link
104  *
105  * @sta: mesh peer link to deactivate
106  *
107  * All mesh paths with this peer as next hop will be flushed
108  *
109  * Locking: the caller must hold sta->lock
110  */
111 static bool __mesh_plink_deactivate(struct sta_info *sta)
112 {
113         struct ieee80211_sub_if_data *sdata = sta->sdata;
114         bool deactivated = false;
115
116         if (sta->plink_state == NL80211_PLINK_ESTAB) {
117                 mesh_plink_dec_estab_count(sdata);
118                 deactivated = true;
119         }
120         sta->plink_state = NL80211_PLINK_BLOCKED;
121         mesh_path_flush_by_nexthop(sta);
122
123         return deactivated;
124 }
125
126 /**
127  * mesh_plink_deactivate - deactivate mesh peer link
128  *
129  * @sta: mesh peer link to deactivate
130  *
131  * All mesh paths with this peer as next hop will be flushed
132  */
133 void mesh_plink_deactivate(struct sta_info *sta)
134 {
135         struct ieee80211_sub_if_data *sdata = sta->sdata;
136         bool deactivated;
137
138         spin_lock_bh(&sta->lock);
139         deactivated = __mesh_plink_deactivate(sta);
140         sta->reason = cpu_to_le16(WLAN_REASON_MESH_PEER_CANCELED);
141         mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
142                             sta->sta.addr, sta->llid, sta->plid,
143                             sta->reason);
144         spin_unlock_bh(&sta->lock);
145
146         if (deactivated)
147                 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
148 }
149
150 static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
151                 enum ieee80211_self_protected_actioncode action,
152                 u8 *da, __le16 llid, __le16 plid, __le16 reason) {
153         struct ieee80211_local *local = sdata->local;
154         struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 +
155                         sdata->u.mesh.ie_len);
156         struct ieee80211_mgmt *mgmt;
157         bool include_plid = false;
158         int ie_len = 4;
159         u16 peering_proto = 0;
160         u8 *pos;
161
162         if (!skb)
163                 return -1;
164         skb_reserve(skb, local->hw.extra_tx_headroom);
165         /* 25 is the size of the common mgmt part (24) plus the size of the
166          * common action part (1)
167          */
168         mgmt = (struct ieee80211_mgmt *)
169                 skb_put(skb, 25 + sizeof(mgmt->u.action.u.self_prot));
170         memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.self_prot));
171         mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
172                                           IEEE80211_STYPE_ACTION);
173         memcpy(mgmt->da, da, ETH_ALEN);
174         memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
175         memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
176         mgmt->u.action.category = WLAN_CATEGORY_SELF_PROTECTED;
177         mgmt->u.action.u.self_prot.action_code = action;
178
179         if (action != WLAN_SP_MESH_PEERING_CLOSE) {
180                 /* capability info */
181                 pos = skb_put(skb, 2);
182                 memset(pos, 0, 2);
183                 if (action == WLAN_SP_MESH_PEERING_CONFIRM) {
184                         /* AID */
185                         pos = skb_put(skb, 2);
186                         memcpy(pos + 2, &plid, 2);
187                 }
188                 if (ieee80211_add_srates_ie(&sdata->vif, skb) ||
189                     ieee80211_add_ext_srates_ie(&sdata->vif, skb) ||
190                     mesh_add_rsn_ie(skb, sdata) ||
191                     mesh_add_meshid_ie(skb, sdata) ||
192                     mesh_add_meshconf_ie(skb, sdata))
193                         return -1;
194         } else {        /* WLAN_SP_MESH_PEERING_CLOSE */
195                 if (mesh_add_meshid_ie(skb, sdata))
196                         return -1;
197         }
198
199         /* Add Mesh Peering Management element */
200         switch (action) {
201         case WLAN_SP_MESH_PEERING_OPEN:
202                 break;
203         case WLAN_SP_MESH_PEERING_CONFIRM:
204                 ie_len += 2;
205                 include_plid = true;
206                 break;
207         case WLAN_SP_MESH_PEERING_CLOSE:
208                 if (plid) {
209                         ie_len += 2;
210                         include_plid = true;
211                 }
212                 ie_len += 2;    /* reason code */
213                 break;
214         default:
215                 return -EINVAL;
216         }
217
218         if (WARN_ON(skb_tailroom(skb) < 2 + ie_len))
219                 return -ENOMEM;
220
221         pos = skb_put(skb, 2 + ie_len);
222         *pos++ = WLAN_EID_PEER_MGMT;
223         *pos++ = ie_len;
224         memcpy(pos, &peering_proto, 2);
225         pos += 2;
226         memcpy(pos, &llid, 2);
227         pos += 2;
228         if (include_plid) {
229                 memcpy(pos, &plid, 2);
230                 pos += 2;
231         }
232         if (action == WLAN_SP_MESH_PEERING_CLOSE) {
233                 memcpy(pos, &reason, 2);
234                 pos += 2;
235         }
236         if (mesh_add_vendor_ies(skb, sdata))
237                 return -1;
238
239         ieee80211_tx_skb(sdata, skb);
240         return 0;
241 }
242
243 void mesh_neighbour_update(u8 *hw_addr, u32 rates,
244                 struct ieee80211_sub_if_data *sdata,
245                 struct ieee802_11_elems *elems)
246 {
247         struct ieee80211_local *local = sdata->local;
248         struct sta_info *sta;
249
250         rcu_read_lock();
251
252         sta = sta_info_get(sdata, hw_addr);
253         if (!sta) {
254                 rcu_read_unlock();
255                 /* Userspace handles peer allocation when security is enabled
256                  * */
257                 if (sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED)
258                         cfg80211_notify_new_peer_candidate(sdata->dev, hw_addr,
259                                         elems->ie_start, elems->total_len,
260                                         GFP_KERNEL);
261                 else
262                         sta = mesh_plink_alloc(sdata, hw_addr, rates);
263                 if (!sta)
264                         return;
265                 if (sta_info_insert_rcu(sta)) {
266                         rcu_read_unlock();
267                         return;
268                 }
269         }
270
271         sta->last_rx = jiffies;
272         sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
273         if (mesh_peer_accepts_plinks(elems) &&
274                         sta->plink_state == NL80211_PLINK_LISTEN &&
275                         sdata->u.mesh.accepting_plinks &&
276                         sdata->u.mesh.mshcfg.auto_open_plinks)
277                 mesh_plink_open(sta);
278
279         rcu_read_unlock();
280 }
281
282 static void mesh_plink_timer(unsigned long data)
283 {
284         struct sta_info *sta;
285         __le16 llid, plid, reason;
286         struct ieee80211_sub_if_data *sdata;
287
288         /*
289          * This STA is valid because sta_info_destroy() will
290          * del_timer_sync() this timer after having made sure
291          * it cannot be readded (by deleting the plink.)
292          */
293         sta = (struct sta_info *) data;
294
295         if (sta->sdata->local->quiescing) {
296                 sta->plink_timer_was_running = true;
297                 return;
298         }
299
300         spin_lock_bh(&sta->lock);
301         if (sta->ignore_plink_timer) {
302                 sta->ignore_plink_timer = false;
303                 spin_unlock_bh(&sta->lock);
304                 return;
305         }
306         mpl_dbg("Mesh plink timer for %pM fired on state %d\n",
307                 sta->sta.addr, sta->plink_state);
308         reason = 0;
309         llid = sta->llid;
310         plid = sta->plid;
311         sdata = sta->sdata;
312
313         switch (sta->plink_state) {
314         case NL80211_PLINK_OPN_RCVD:
315         case NL80211_PLINK_OPN_SNT:
316                 /* retry timer */
317                 if (sta->plink_retries < dot11MeshMaxRetries(sdata)) {
318                         u32 rand;
319                         mpl_dbg("Mesh plink for %pM (retry, timeout): %d %d\n",
320                                 sta->sta.addr, sta->plink_retries,
321                                 sta->plink_timeout);
322                         get_random_bytes(&rand, sizeof(u32));
323                         sta->plink_timeout = sta->plink_timeout +
324                                              rand % sta->plink_timeout;
325                         ++sta->plink_retries;
326                         mod_plink_timer(sta, sta->plink_timeout);
327                         spin_unlock_bh(&sta->lock);
328                         mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,
329                                             sta->sta.addr, llid, 0, 0);
330                         break;
331                 }
332                 reason = cpu_to_le16(WLAN_REASON_MESH_MAX_RETRIES);
333                 /* fall through on else */
334         case NL80211_PLINK_CNF_RCVD:
335                 /* confirm timer */
336                 if (!reason)
337                         reason = cpu_to_le16(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
338                 sta->plink_state = NL80211_PLINK_HOLDING;
339                 mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
340                 spin_unlock_bh(&sta->lock);
341                 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
342                                     sta->sta.addr, llid, plid, reason);
343                 break;
344         case NL80211_PLINK_HOLDING:
345                 /* holding timer */
346                 del_timer(&sta->plink_timer);
347                 mesh_plink_fsm_restart(sta);
348                 spin_unlock_bh(&sta->lock);
349                 break;
350         default:
351                 spin_unlock_bh(&sta->lock);
352                 break;
353         }
354 }
355
356 #ifdef CONFIG_PM
357 void mesh_plink_quiesce(struct sta_info *sta)
358 {
359         if (del_timer_sync(&sta->plink_timer))
360                 sta->plink_timer_was_running = true;
361 }
362
363 void mesh_plink_restart(struct sta_info *sta)
364 {
365         if (sta->plink_timer_was_running) {
366                 add_timer(&sta->plink_timer);
367                 sta->plink_timer_was_running = false;
368         }
369 }
370 #endif
371
372 static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout)
373 {
374         sta->plink_timer.expires = jiffies + (HZ * timeout / 1000);
375         sta->plink_timer.data = (unsigned long) sta;
376         sta->plink_timer.function = mesh_plink_timer;
377         sta->plink_timeout = timeout;
378         add_timer(&sta->plink_timer);
379 }
380
381 int mesh_plink_open(struct sta_info *sta)
382 {
383         __le16 llid;
384         struct ieee80211_sub_if_data *sdata = sta->sdata;
385
386         if (!test_sta_flags(sta, WLAN_STA_AUTH))
387                 return -EPERM;
388
389         spin_lock_bh(&sta->lock);
390         get_random_bytes(&llid, 2);
391         sta->llid = llid;
392         if (sta->plink_state != NL80211_PLINK_LISTEN) {
393                 spin_unlock_bh(&sta->lock);
394                 return -EBUSY;
395         }
396         sta->plink_state = NL80211_PLINK_OPN_SNT;
397         mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
398         spin_unlock_bh(&sta->lock);
399         mpl_dbg("Mesh plink: starting establishment with %pM\n",
400                 sta->sta.addr);
401
402         return mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,
403                                    sta->sta.addr, llid, 0, 0);
404 }
405
406 void mesh_plink_block(struct sta_info *sta)
407 {
408         struct ieee80211_sub_if_data *sdata = sta->sdata;
409         bool deactivated;
410
411         spin_lock_bh(&sta->lock);
412         deactivated = __mesh_plink_deactivate(sta);
413         sta->plink_state = NL80211_PLINK_BLOCKED;
414         spin_unlock_bh(&sta->lock);
415
416         if (deactivated)
417                 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
418 }
419
420
421 void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt,
422                          size_t len, struct ieee80211_rx_status *rx_status)
423 {
424         struct ieee80211_local *local = sdata->local;
425         struct ieee802_11_elems elems;
426         struct sta_info *sta;
427         enum plink_event event;
428         enum ieee80211_self_protected_actioncode ftype;
429         size_t baselen;
430         bool deactivated, matches_local = true;
431         u8 ie_len;
432         u8 *baseaddr;
433         __le16 plid, llid, reason;
434 #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
435         static const char *mplstates[] = {
436                 [NL80211_PLINK_LISTEN] = "LISTEN",
437                 [NL80211_PLINK_OPN_SNT] = "OPN-SNT",
438                 [NL80211_PLINK_OPN_RCVD] = "OPN-RCVD",
439                 [NL80211_PLINK_CNF_RCVD] = "CNF_RCVD",
440                 [NL80211_PLINK_ESTAB] = "ESTAB",
441                 [NL80211_PLINK_HOLDING] = "HOLDING",
442                 [NL80211_PLINK_BLOCKED] = "BLOCKED"
443         };
444 #endif
445
446         /* need action_code, aux */
447         if (len < IEEE80211_MIN_ACTION_SIZE + 3)
448                 return;
449
450         if (is_multicast_ether_addr(mgmt->da)) {
451                 mpl_dbg("Mesh plink: ignore frame from multicast address");
452                 return;
453         }
454
455         baseaddr = mgmt->u.action.u.self_prot.variable;
456         baselen = (u8 *) mgmt->u.action.u.self_prot.variable - (u8 *) mgmt;
457         if (mgmt->u.action.u.self_prot.action_code ==
458                                                 WLAN_SP_MESH_PEERING_CONFIRM) {
459                 baseaddr += 4;
460                 baselen += 4;
461         }
462         ieee802_11_parse_elems(baseaddr, len - baselen, &elems);
463         if (!elems.peering) {
464                 mpl_dbg("Mesh plink: missing necessary peer link ie\n");
465                 return;
466         }
467         if (elems.rsn_len &&
468                         sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) {
469                 mpl_dbg("Mesh plink: can't establish link with secure peer\n");
470                 return;
471         }
472
473         ftype = mgmt->u.action.u.self_prot.action_code;
474         ie_len = elems.peering_len;
475         if ((ftype == WLAN_SP_MESH_PEERING_OPEN && ie_len != 4) ||
476             (ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 6) ||
477             (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 6
478                                                         && ie_len != 8)) {
479                 mpl_dbg("Mesh plink: incorrect plink ie length %d %d\n",
480                     ftype, ie_len);
481                 return;
482         }
483
484         if (ftype != WLAN_SP_MESH_PEERING_CLOSE &&
485                                 (!elems.mesh_id || !elems.mesh_config)) {
486                 mpl_dbg("Mesh plink: missing necessary ie\n");
487                 return;
488         }
489         /* Note the lines below are correct, the llid in the frame is the plid
490          * from the point of view of this host.
491          */
492         memcpy(&plid, PLINK_GET_LLID(elems.peering), 2);
493         if (ftype == WLAN_SP_MESH_PEERING_CONFIRM ||
494             (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8))
495                 memcpy(&llid, PLINK_GET_PLID(elems.peering), 2);
496
497         rcu_read_lock();
498
499         sta = sta_info_get(sdata, mgmt->sa);
500         if (!sta && ftype != WLAN_SP_MESH_PEERING_OPEN) {
501                 mpl_dbg("Mesh plink: cls or cnf from unknown peer\n");
502                 rcu_read_unlock();
503                 return;
504         }
505
506         if (sta && !test_sta_flags(sta, WLAN_STA_AUTH)) {
507                 mpl_dbg("Mesh plink: Action frame from non-authed peer\n");
508                 rcu_read_unlock();
509                 return;
510         }
511
512         if (sta && sta->plink_state == NL80211_PLINK_BLOCKED) {
513                 rcu_read_unlock();
514                 return;
515         }
516
517         /* Now we will figure out the appropriate event... */
518         event = PLINK_UNDEFINED;
519         if (ftype != WLAN_SP_MESH_PEERING_CLOSE &&
520             (!mesh_matches_local(&elems, sdata))) {
521                 matches_local = false;
522                 switch (ftype) {
523                 case WLAN_SP_MESH_PEERING_OPEN:
524                         event = OPN_RJCT;
525                         break;
526                 case WLAN_SP_MESH_PEERING_CONFIRM:
527                         event = CNF_RJCT;
528                         break;
529                 default:
530                         break;
531                 }
532         }
533
534         if (!sta && !matches_local) {
535                 rcu_read_unlock();
536                 reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
537                 llid = 0;
538                 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
539                                     mgmt->sa, llid, plid, reason);
540                 return;
541         } else if (!sta) {
542                 /* ftype == WLAN_SP_MESH_PEERING_OPEN */
543                 u32 rates;
544
545                 rcu_read_unlock();
546
547                 if (!mesh_plink_free_count(sdata)) {
548                         mpl_dbg("Mesh plink error: no more free plinks\n");
549                         return;
550                 }
551
552                 rates = ieee80211_sta_get_rates(local, &elems, rx_status->band);
553                 sta = mesh_plink_alloc(sdata, mgmt->sa, rates);
554                 if (!sta) {
555                         mpl_dbg("Mesh plink error: plink table full\n");
556                         return;
557                 }
558                 if (sta_info_insert_rcu(sta)) {
559                         rcu_read_unlock();
560                         return;
561                 }
562                 event = OPN_ACPT;
563                 spin_lock_bh(&sta->lock);
564         } else if (matches_local) {
565                 spin_lock_bh(&sta->lock);
566                 switch (ftype) {
567                 case WLAN_SP_MESH_PEERING_OPEN:
568                         if (!mesh_plink_free_count(sdata) ||
569                             (sta->plid && sta->plid != plid))
570                                 event = OPN_IGNR;
571                         else
572                                 event = OPN_ACPT;
573                         break;
574                 case WLAN_SP_MESH_PEERING_CONFIRM:
575                         if (!mesh_plink_free_count(sdata) ||
576                             (sta->llid != llid || sta->plid != plid))
577                                 event = CNF_IGNR;
578                         else
579                                 event = CNF_ACPT;
580                         break;
581                 case WLAN_SP_MESH_PEERING_CLOSE:
582                         if (sta->plink_state == NL80211_PLINK_ESTAB)
583                                 /* Do not check for llid or plid. This does not
584                                  * follow the standard but since multiple plinks
585                                  * per sta are not supported, it is necessary in
586                                  * order to avoid a livelock when MP A sees an
587                                  * establish peer link to MP B but MP B does not
588                                  * see it. This can be caused by a timeout in
589                                  * B's peer link establishment or B beign
590                                  * restarted.
591                                  */
592                                 event = CLS_ACPT;
593                         else if (sta->plid != plid)
594                                 event = CLS_IGNR;
595                         else if (ie_len == 7 && sta->llid != llid)
596                                 event = CLS_IGNR;
597                         else
598                                 event = CLS_ACPT;
599                         break;
600                 default:
601                         mpl_dbg("Mesh plink: unknown frame subtype\n");
602                         spin_unlock_bh(&sta->lock);
603                         rcu_read_unlock();
604                         return;
605                 }
606         } else {
607                 spin_lock_bh(&sta->lock);
608         }
609
610         mpl_dbg("Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n",
611                 mgmt->sa, mplstates[sta->plink_state],
612                 le16_to_cpu(sta->llid), le16_to_cpu(sta->plid),
613                 event);
614         reason = 0;
615         switch (sta->plink_state) {
616                 /* spin_unlock as soon as state is updated at each case */
617         case NL80211_PLINK_LISTEN:
618                 switch (event) {
619                 case CLS_ACPT:
620                         mesh_plink_fsm_restart(sta);
621                         spin_unlock_bh(&sta->lock);
622                         break;
623                 case OPN_ACPT:
624                         sta->plink_state = NL80211_PLINK_OPN_RCVD;
625                         sta->plid = plid;
626                         get_random_bytes(&llid, 2);
627                         sta->llid = llid;
628                         mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
629                         spin_unlock_bh(&sta->lock);
630                         mesh_plink_frame_tx(sdata,
631                                             WLAN_SP_MESH_PEERING_OPEN,
632                                             sta->sta.addr, llid, 0, 0);
633                         mesh_plink_frame_tx(sdata,
634                                             WLAN_SP_MESH_PEERING_CONFIRM,
635                                             sta->sta.addr, llid, plid, 0);
636                         break;
637                 default:
638                         spin_unlock_bh(&sta->lock);
639                         break;
640                 }
641                 break;
642
643         case NL80211_PLINK_OPN_SNT:
644                 switch (event) {
645                 case OPN_RJCT:
646                 case CNF_RJCT:
647                         reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
648                 case CLS_ACPT:
649                         if (!reason)
650                                 reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
651                         sta->reason = reason;
652                         sta->plink_state = NL80211_PLINK_HOLDING;
653                         if (!mod_plink_timer(sta,
654                                              dot11MeshHoldingTimeout(sdata)))
655                                 sta->ignore_plink_timer = true;
656
657                         llid = sta->llid;
658                         spin_unlock_bh(&sta->lock);
659                         mesh_plink_frame_tx(sdata,
660                                             WLAN_SP_MESH_PEERING_CLOSE,
661                                             sta->sta.addr, llid, plid, reason);
662                         break;
663                 case OPN_ACPT:
664                         /* retry timer is left untouched */
665                         sta->plink_state = NL80211_PLINK_OPN_RCVD;
666                         sta->plid = plid;
667                         llid = sta->llid;
668                         spin_unlock_bh(&sta->lock);
669                         mesh_plink_frame_tx(sdata,
670                                             WLAN_SP_MESH_PEERING_CONFIRM,
671                                             sta->sta.addr, llid, plid, 0);
672                         break;
673                 case CNF_ACPT:
674                         sta->plink_state = NL80211_PLINK_CNF_RCVD;
675                         if (!mod_plink_timer(sta,
676                                              dot11MeshConfirmTimeout(sdata)))
677                                 sta->ignore_plink_timer = true;
678
679                         spin_unlock_bh(&sta->lock);
680                         break;
681                 default:
682                         spin_unlock_bh(&sta->lock);
683                         break;
684                 }
685                 break;
686
687         case NL80211_PLINK_OPN_RCVD:
688                 switch (event) {
689                 case OPN_RJCT:
690                 case CNF_RJCT:
691                         reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
692                 case CLS_ACPT:
693                         if (!reason)
694                                 reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
695                         sta->reason = reason;
696                         sta->plink_state = NL80211_PLINK_HOLDING;
697                         if (!mod_plink_timer(sta,
698                                              dot11MeshHoldingTimeout(sdata)))
699                                 sta->ignore_plink_timer = true;
700
701                         llid = sta->llid;
702                         spin_unlock_bh(&sta->lock);
703                         mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
704                                             sta->sta.addr, llid, plid, reason);
705                         break;
706                 case OPN_ACPT:
707                         llid = sta->llid;
708                         spin_unlock_bh(&sta->lock);
709                         mesh_plink_frame_tx(sdata,
710                                             WLAN_SP_MESH_PEERING_CONFIRM,
711                                             sta->sta.addr, llid, plid, 0);
712                         break;
713                 case CNF_ACPT:
714                         del_timer(&sta->plink_timer);
715                         sta->plink_state = NL80211_PLINK_ESTAB;
716                         spin_unlock_bh(&sta->lock);
717                         mesh_plink_inc_estab_count(sdata);
718                         ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
719                         mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
720                                 sta->sta.addr);
721                         break;
722                 default:
723                         spin_unlock_bh(&sta->lock);
724                         break;
725                 }
726                 break;
727
728         case NL80211_PLINK_CNF_RCVD:
729                 switch (event) {
730                 case OPN_RJCT:
731                 case CNF_RJCT:
732                         reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
733                 case CLS_ACPT:
734                         if (!reason)
735                                 reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
736                         sta->reason = reason;
737                         sta->plink_state = NL80211_PLINK_HOLDING;
738                         if (!mod_plink_timer(sta,
739                                              dot11MeshHoldingTimeout(sdata)))
740                                 sta->ignore_plink_timer = true;
741
742                         llid = sta->llid;
743                         spin_unlock_bh(&sta->lock);
744                         mesh_plink_frame_tx(sdata,
745                                             WLAN_SP_MESH_PEERING_CLOSE,
746                                             sta->sta.addr, llid, plid, reason);
747                         break;
748                 case OPN_ACPT:
749                         del_timer(&sta->plink_timer);
750                         sta->plink_state = NL80211_PLINK_ESTAB;
751                         spin_unlock_bh(&sta->lock);
752                         mesh_plink_inc_estab_count(sdata);
753                         ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
754                         mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
755                                 sta->sta.addr);
756                         mesh_plink_frame_tx(sdata,
757                                             WLAN_SP_MESH_PEERING_CONFIRM,
758                                             sta->sta.addr, llid, plid, 0);
759                         break;
760                 default:
761                         spin_unlock_bh(&sta->lock);
762                         break;
763                 }
764                 break;
765
766         case NL80211_PLINK_ESTAB:
767                 switch (event) {
768                 case CLS_ACPT:
769                         reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
770                         sta->reason = reason;
771                         deactivated = __mesh_plink_deactivate(sta);
772                         sta->plink_state = NL80211_PLINK_HOLDING;
773                         llid = sta->llid;
774                         mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
775                         spin_unlock_bh(&sta->lock);
776                         if (deactivated)
777                                 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
778                         mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
779                                             sta->sta.addr, llid, plid, reason);
780                         break;
781                 case OPN_ACPT:
782                         llid = sta->llid;
783                         spin_unlock_bh(&sta->lock);
784                         mesh_plink_frame_tx(sdata,
785                                             WLAN_SP_MESH_PEERING_CONFIRM,
786                                             sta->sta.addr, llid, plid, 0);
787                         break;
788                 default:
789                         spin_unlock_bh(&sta->lock);
790                         break;
791                 }
792                 break;
793         case NL80211_PLINK_HOLDING:
794                 switch (event) {
795                 case CLS_ACPT:
796                         if (del_timer(&sta->plink_timer))
797                                 sta->ignore_plink_timer = 1;
798                         mesh_plink_fsm_restart(sta);
799                         spin_unlock_bh(&sta->lock);
800                         break;
801                 case OPN_ACPT:
802                 case CNF_ACPT:
803                 case OPN_RJCT:
804                 case CNF_RJCT:
805                         llid = sta->llid;
806                         reason = sta->reason;
807                         spin_unlock_bh(&sta->lock);
808                         mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
809                                             sta->sta.addr, llid, plid, reason);
810                         break;
811                 default:
812                         spin_unlock_bh(&sta->lock);
813                 }
814                 break;
815         default:
816                 /* should not get here, PLINK_BLOCKED is dealt with at the
817                  * beginning of the function
818                  */
819                 spin_unlock_bh(&sta->lock);
820                 break;
821         }
822
823         rcu_read_unlock();
824 }