fix mkimage compile
[openwrt.git] / package / madwifi / patches / 010-refcount_merge.patch
1 diff -ur madwifi.old/ath/if_ath.c madwifi.dev/ath/if_ath.c
2 --- madwifi.old/ath/if_ath.c    2007-05-18 13:19:16.000000000 +0200
3 +++ madwifi.dev/ath/if_ath.c    2007-05-21 08:10:46.864754176 +0200
4 @@ -158,8 +158,7 @@
5  static int ath_desc_alloc(struct ath_softc *);
6  static void ath_desc_free(struct ath_softc *);
7  static void ath_desc_swap(struct ath_desc *);
8 -static struct ieee80211_node *ath_node_alloc(struct ieee80211_node_table *,
9 -       struct ieee80211vap *);
10 +static struct ieee80211_node *ath_node_alloc(struct ieee80211vap *);
11  static void ath_node_cleanup(struct ieee80211_node *);
12  static void ath_node_free(struct ieee80211_node *);
13  static u_int8_t ath_node_getrssi(const struct ieee80211_node *);
14 @@ -2385,7 +2384,7 @@
15                 if (ath_tx_start(sc->sc_dev, ni, bf_ff, bf_ff->bf_skb, 0) == 0)
16                         continue;
17         bad:
18 -               ieee80211_free_node(ni);
19 +               ieee80211_unref_node(&ni);
20                 if (bf_ff->bf_skb != NULL) {
21                         dev_kfree_skb(bf_ff->bf_skb);
22                         bf_ff->bf_skb = NULL;
23 @@ -2525,8 +2524,10 @@
24                         skb = bf->bf_skb;
25                         ATH_FF_MAGIC_PUT(skb);
26  
27 +#if 0
28                         /* decrement extra node reference made when an_tx_ffbuf[] was set */
29 -                       //ieee80211_free_node(ni); /* XXX where was it set ? */
30 +                       ieee80211_unref_node(&ni); /* XXX where was it set ? */
31 +#endif
32  
33                         DPRINTF(sc, ATH_DEBUG_XMIT | ATH_DEBUG_FF,
34                                 "%s: aggregating fast-frame\n", __func__);
35 @@ -2585,7 +2586,7 @@
36                 ff_flushbad:
37                         DPRINTF(sc, ATH_DEBUG_XMIT | ATH_DEBUG_FF,
38                                 "%s: ff stageq flush failure\n", __func__);
39 -                       ieee80211_free_node(ni);
40 +                       ieee80211_unref_node(&ni);
41                         if (bf_ff->bf_skb) {
42                                 dev_kfree_skb(bf_ff->bf_skb);
43                                 bf_ff->bf_skb = NULL;
44 @@ -2707,7 +2708,7 @@
45                         tbf->bf_node = NULL;
46                         
47                         if (ni != NULL) 
48 -                               ieee80211_free_node(ni);
49 +                               ieee80211_unref_node(&ni);
50  
51                         STAILQ_INSERT_TAIL(&sc->sc_txbuf, tbf, bf_list);
52                 }
53 @@ -2789,7 +2790,7 @@
54         /* fall thru... */
55  bad:
56         if (ni != NULL)
57 -               ieee80211_free_node(ni);
58 +               ieee80211_unref_node(&ni);
59         if (bf != NULL) {
60                 bf->bf_skb = NULL;
61                 bf->bf_node = NULL;
62 @@ -3178,7 +3179,7 @@
63          */
64         ni = sc->sc_keyixmap[keyix];
65         if (ni != NULL) {
66 -               ieee80211_free_node(ni);
67 +               ieee80211_unref_node(&ni);
68                 sc->sc_keyixmap[keyix] = NULL;
69         }
70         /*
71 @@ -3189,7 +3190,7 @@
72                 ath_hal_keyreset(ah, keyix + 32);       /* RX key */
73                 ni = sc->sc_keyixmap[keyix + 32];
74                 if (ni != NULL) {                       /* as above... */
75 -                       ieee80211_free_node(ni);
76 +                       ieee80211_unref_node(&ni);
77                         sc->sc_keyixmap[keyix + 32] = NULL;
78                 }
79         }
80 @@ -3202,7 +3203,7 @@
81                         ath_hal_keyreset(ah, keyix + rxkeyoff);
82                         ni = sc->sc_keyixmap[keyix + rxkeyoff];
83                         if (ni != NULL) {       /* as above... */
84 -                               ieee80211_free_node(ni);
85 +                               ieee80211_unref_node(&ni);
86                                 sc->sc_keyixmap[keyix + rxkeyoff] = NULL;
87                         }
88                 }
89 @@ -3764,10 +3765,8 @@
90                 dev_kfree_skb(bf->bf_skb);
91                 bf->bf_skb = NULL;
92         }
93 -       if (bf->bf_node != NULL) {
94 -               ieee80211_free_node(bf->bf_node);
95 -               bf->bf_node = NULL;
96 -       }
97 +       if (bf->bf_node != NULL)
98 +               ieee80211_unref_node(&bf->bf_node);
99  
100         /*
101          * NB: the beacon data buffer must be 32-bit aligned;
102 @@ -3808,7 +3807,7 @@
103                 DPRINTF(sc, ATH_DEBUG_BEACON,
104                         "%s: %s beacons, bslot %d intval %u tsfadjust(Kus) %llu\n",
105                         __func__, sc->sc_stagbeacons ? "stagger" : "burst",
106 -                       avp->av_bslot, ni->ni_intval, (unsigned long long) tuadjust);
107 +                       avp->av_bslot, ni->ni_intval, (long long) tuadjust);
108  
109                 wh = (struct ieee80211_frame *) skb->data;
110                 memcpy(&wh[1], &tsfadjust, sizeof(tsfadjust));
111 @@ -4128,7 +4127,7 @@
112                 vap = sc->sc_bslot[(slot + 1) % ATH_BCBUF];
113                 DPRINTF(sc, ATH_DEBUG_BEACON_PROC,
114                         "%s: slot %d [tsf %llu tsftu %u intval %u] vap %p\n",
115 -                       __func__, slot, (unsigned long long) tsf, tsftu, ic->ic_lintval, vap);
116 +                       __func__, slot, (long long) tsf, tsftu, ic->ic_lintval, vap);
117                 bfaddr = 0;
118                 if (vap != NULL) {
119                         bf = ath_beacon_generate(sc, vap, needmark);
120 @@ -4309,10 +4308,8 @@
121                 dev_kfree_skb(bf->bf_skb);
122                 bf->bf_skb = NULL;
123         }
124 -       if (bf->bf_node != NULL) {
125 -               ieee80211_free_node(bf->bf_node);
126 -               bf->bf_node = NULL;
127 -       }
128 +       if (bf->bf_node != NULL) 
129 +               ieee80211_unref_node(&bf->bf_node);
130         STAILQ_INSERT_TAIL(&sc->sc_bbuf, bf, bf_list);
131  }
132  
133 @@ -4331,10 +4328,8 @@
134                         dev_kfree_skb(bf->bf_skb);
135                         bf->bf_skb = NULL;
136                 }
137 -               if (bf->bf_node != NULL) {
138 -                       ieee80211_free_node(bf->bf_node);
139 -                       bf->bf_node = NULL;
140 -               }
141 +               if (bf->bf_node != NULL)
142 +                       ieee80211_unref_node(&bf->bf_node);
143         }
144  }
145  
146 @@ -4620,7 +4615,7 @@
147                         /*
148                          * Reclaim node reference.
149                          */
150 -                       ieee80211_free_node(ni);
151 +                       ieee80211_unref_node(&ni);
152                 }
153         }
154  
155 @@ -4679,37 +4674,39 @@
156  }
157  
158  static struct ieee80211_node *
159 -ath_node_alloc(struct ieee80211_node_table *nt,struct ieee80211vap *vap)
160 +ath_node_alloc(struct ieee80211vap *vap)
161  {
162 -       struct ath_softc *sc = nt->nt_ic->ic_dev->priv;
163 +       struct ath_softc *sc = vap->iv_ic->ic_dev->priv;
164         const size_t space = sizeof(struct ath_node) + sc->sc_rc->arc_space;
165         struct ath_node *an;
166  
167         an = kmalloc(space, GFP_ATOMIC);
168 -       if (an == NULL)
169 -               return NULL;
170 -       memset(an, 0, space);
171 -       an->an_decomp_index = INVALID_DECOMP_INDEX;
172 -       an->an_avgrssi = ATH_RSSI_DUMMY_MARKER;
173 -       an->an_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER;
174 -       an->an_halstats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER;
175 -       an->an_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER;
176 -       /*
177 -        * ath_rate_node_init needs a VAP pointer in node
178 -        * to decide which mgt rate to use
179 -        */
180 -       an->an_node.ni_vap = vap;
181 -       sc->sc_rc->ops->node_init(sc, an);
182 -
183 -       /* U-APSD init */
184 -       STAILQ_INIT(&an->an_uapsd_q);
185 -       an->an_uapsd_qdepth = 0;
186 -       STAILQ_INIT(&an->an_uapsd_overflowq);
187 -       an->an_uapsd_overflowqdepth = 0;
188 -       ATH_NODE_UAPSD_LOCK_INIT(an);
189 +       if (an != NULL) {
190 +               memset(an, 0, space);
191 +               an->an_decomp_index = INVALID_DECOMP_INDEX;
192 +               an->an_avgrssi = ATH_RSSI_DUMMY_MARKER;
193 +               an->an_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER;
194 +               an->an_halstats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER;
195 +               an->an_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER;
196 +               /*
197 +                * ath_rate_node_init needs a vap pointer in node
198 +                * to decide which mgt rate to use
199 +                */
200 +               an->an_node.ni_vap = vap;
201 +               sc->sc_rc->ops->node_init(sc, an);
202  
203 -       DPRINTF(sc, ATH_DEBUG_NODE, "%s: an %p\n", __func__, an);
204 -       return &an->an_node;
205 +               /* U-APSD init */
206 +               STAILQ_INIT(&an->an_uapsd_q);
207 +               an->an_uapsd_qdepth = 0;
208 +               STAILQ_INIT(&an->an_uapsd_overflowq);
209 +               an->an_uapsd_overflowqdepth = 0;
210 +               ATH_NODE_UAPSD_LOCK_INIT(an);
211 +               
212 +               DPRINTF(sc, ATH_DEBUG_NODE, "%s: an %p\n", __func__, an);
213 +               return &an->an_node;
214 +       } else {
215 +               return NULL;
216 +       }
217  }
218  
219  static void
220 @@ -4719,6 +4716,7 @@
221         struct ath_softc *sc = ni->ni_ic->ic_dev->priv;
222         struct ath_node *an = ATH_NODE(ni);
223         struct ath_buf *bf;
224 +       struct ieee80211_cb *cb = NULL;
225         
226         /*
227          * U-APSD cleanup
228 @@ -4733,15 +4731,18 @@
229         while (an->an_uapsd_qdepth) {
230                 bf = STAILQ_FIRST(&an->an_uapsd_q);
231                 STAILQ_REMOVE_HEAD(&an->an_uapsd_q, bf_list);
232 -               bf->bf_desc->ds_link = 0;
233  
234 +               cb = (struct ieee80211_cb *) bf->bf_skb->cb;
235 +               ieee80211_unref_node(&cb->ni);
236                 dev_kfree_skb_any(bf->bf_skb);
237 +
238 +               bf->bf_desc->ds_link = 0;
239                 bf->bf_skb = NULL;
240                 bf->bf_node = NULL;
241 +
242                 ATH_TXBUF_LOCK_IRQ(sc);
243                 STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
244                 ATH_TXBUF_UNLOCK_IRQ(sc);
245 -               ieee80211_free_node(ni);
246  
247                 an->an_uapsd_qdepth--;
248         }
249 @@ -4749,19 +4750,25 @@
250         while (an->an_uapsd_overflowqdepth) {
251                 bf = STAILQ_FIRST(&an->an_uapsd_overflowq);
252                 STAILQ_REMOVE_HEAD(&an->an_uapsd_overflowq, bf_list);
253 -               bf->bf_desc->ds_link = 0;
254  
255 +               cb = (struct ieee80211_cb *) bf->bf_skb->cb;
256 +               ieee80211_unref_node(&cb->ni);
257                 dev_kfree_skb_any(bf->bf_skb);
258 +
259                 bf->bf_skb = NULL;
260                 bf->bf_node = NULL;
261 +               bf->bf_desc->ds_link = 0;
262 +               
263                 ATH_TXBUF_LOCK_IRQ(sc);
264                 STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
265                 ATH_TXBUF_UNLOCK_IRQ(sc);
266 -               ieee80211_free_node(ni);
267  
268                 an->an_uapsd_overflowqdepth--;
269         }
270  
271 +       /* Clean up node-specific rate things - this currently appears to always be a no-op */
272 +       sc->sc_rc->ops->node_cleanup(sc, ATH_NODE(ni));
273 +
274         ATH_NODE_UAPSD_LOCK_IRQ(an);
275         sc->sc_node_cleanup(ni);
276         ATH_NODE_UAPSD_UNLOCK_IRQ(an);
277 @@ -4772,7 +4779,6 @@
278  {
279         struct ath_softc *sc = ni->ni_ic->ic_dev->priv;
280  
281 -       sc->sc_rc->ops->node_cleanup(sc, ATH_NODE(ni));
282         sc->sc_node_free(ni);
283  #ifdef ATH_SUPERG_XR
284         ath_grppoll_period_update(sc);
285 @@ -5660,7 +5666,7 @@
286                         an = ATH_NODE(ieee80211_ref_node(ni));
287                         ATH_RSSI_LPF(an->an_avgrssi, rs->rs_rssi);
288                         type = ieee80211_input(ni, skb, rs->rs_rssi, rs->rs_tstamp);
289 -                       ieee80211_free_node(ni);
290 +                       ieee80211_unref_node(&ni);
291                 } else {
292                         /*
293                          * No key index or no entry, do a lookup and
294 @@ -5682,7 +5688,7 @@
295                                 if (keyix != IEEE80211_KEYIX_NONE &&
296                                     sc->sc_keyixmap[keyix] == NULL)
297                                         sc->sc_keyixmap[keyix] = ieee80211_ref_node(ni);
298 -                               ieee80211_free_node(ni); 
299 +                               ieee80211_unref_node(&ni); 
300                         } else
301                                 type = ieee80211_input_all(ic, skb,
302                                         rs->rs_rssi, rs->rs_tstamp);
303 @@ -6478,8 +6484,7 @@
304                 STAILQ_REMOVE_HEAD(&an->an_uapsd_q, bf_list);
305                 dev_kfree_skb(lastbuf->bf_skb);
306                 lastbuf->bf_skb = NULL;
307 -               ieee80211_free_node(lastbuf->bf_node);
308 -               lastbuf->bf_node = NULL;
309 +               ieee80211_unref_node(&lastbuf->bf_node);
310                 ATH_TXBUF_LOCK_IRQ(sc);
311                 STAILQ_INSERT_TAIL(&sc->sc_txbuf, lastbuf, bf_list);
312                 ATH_TXBUF_UNLOCK_IRQ(sc);
313 @@ -7229,7 +7234,7 @@
314                          *     this is a DEAUTH message that was sent and the
315                          *     node was timed out due to inactivity.
316                          */
317 -                        ieee80211_free_node(ni); 
318 +                        ieee80211_unref_node(&ni); 
319                 }
320  
321                 bus_unmap_single(sc->sc_bdev, bf->bf_skbaddr, 
322 @@ -7474,7 +7479,7 @@
323                 }
324  #endif /* ATH_SUPERG_FF */
325                 if (bf->bf_node)
326 -                       ieee80211_free_node(bf->bf_node);
327 +                       ieee80211_unref_node(&bf->bf_node);
328  
329                 bf->bf_skb = NULL;
330                 bf->bf_node = NULL;
331 diff -ur madwifi.old/net80211/ieee80211_input.c madwifi.dev/net80211/ieee80211_input.c
332 --- madwifi.old/net80211/ieee80211_input.c      2007-05-18 13:19:16.000000000 +0200
333 +++ madwifi.dev/net80211/ieee80211_input.c      2007-05-21 08:10:46.865754024 +0200
334 @@ -489,7 +489,7 @@
335                                         nt = &ic->ic_sta;
336                                         ni_wds = ieee80211_find_wds_node(nt, wh->i_addr3);
337                                         if (ni_wds) {
338 -                                               ieee80211_free_node(ni_wds); /* Decr ref count */
339 +                                               ieee80211_unref_node(&ni_wds); /* Decr ref count */
340                                                 IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
341                                                         wh, NULL, "%s",
342                                                         "multicast echo originated from node behind me");
343 @@ -543,10 +543,12 @@
344                          * the node table for the packet source address (addr4).
345                          * If not, add one.
346                          */
347 +                       /* XXX: Useless node mgmt API; make better */
348                         if (dir == IEEE80211_FC1_DIR_DSTODS) {
349                                 struct ieee80211_node_table *nt;
350                                 struct ieee80211_frame_addr4 *wh4;
351                                 struct ieee80211_node *ni_wds;
352 +
353                                 if (!(vap->iv_flags_ext & IEEE80211_FEXT_WDS)) {
354                                         IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
355                                                 wh, "data", "%s", "4 addr not allowed");
356 @@ -569,7 +571,7 @@
357                                 if (ni_wds == NULL)
358                                         ieee80211_add_wds_addr(nt, ni, wh4->i_addr4, 0);
359                                 else
360 -                                       ieee80211_free_node(ni_wds); /* Decr ref count */
361 +                                       ieee80211_unref_node(&ni_wds); /* Decr. ref count */
362                         }
363                         
364                         /*
365 @@ -936,7 +938,7 @@
366                 }
367                 ni = ieee80211_ref_node(vap->iv_bss);
368                 type = ieee80211_input(ni, skb1, rssi, rstamp);
369 -               ieee80211_free_node(ni);
370 +               ieee80211_unref_node(&ni);
371         }
372         if (skb != NULL)                /* no vaps, reclaim skb */
373                 dev_kfree_skb(skb);
374 @@ -986,22 +988,14 @@
375         }
376  
377         /*
378 -        * Use this lock to make sure ni->ni_rxfrag is
379 -        * not freed by the timer process while we use it.
380 -        * XXX bogus
381 -        */
382 -       IEEE80211_NODE_LOCK_IRQ(ni->ni_table);
383 -
384 -       /*
385          * Update the time stamp.  As a side effect, it
386          * also makes sure that the timer will not change
387          * ni->ni_rxfrag for at least 1 second, or in
388          * other words, for the remaining of this function.
389 +        * XXX HUGE HORRIFIC HACK
390          */
391         ni->ni_rxfragstamp = jiffies;
392  
393 -       IEEE80211_NODE_UNLOCK_IRQ(ni->ni_table);
394 -
395         /*
396          * Validate that fragment is in order and
397          * related to the previous ones.
398 @@ -1130,7 +1124,7 @@
399                                         skb = NULL;
400                                 }
401                                 /* XXX statistic? */
402 -                               ieee80211_free_node(ni1);
403 +                               ieee80211_unref_node(&ni1);
404                         }
405                 }
406                 if (skb1 != NULL) {
407 @@ -1265,6 +1259,7 @@
408         int rssi, u_int32_t rstamp, u_int16_t seq, u_int16_t status)
409  {
410         struct ieee80211vap *vap = ni->ni_vap;
411 +       unsigned int tmpnode = 0;
412  
413         if (ni->ni_authmode == IEEE80211_AUTH_SHARED) {
414                 IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_AUTH,
415 @@ -1272,22 +1267,21 @@
416                         "bad sta auth mode %u", ni->ni_authmode);
417                 vap->iv_stats.is_rx_bad_auth++; /* XXX maybe a unique error? */
418                 if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
419 -                       /* XXX hack to workaround calling convention */
420 -
421 -                       /* XXX To send the frame to the requesting STA, we have to
422 -                        * create a node for the station that we're going to reject.
423 -                        * The node will be freed automatically */
424                         if (ni == vap->iv_bss) {
425 -                               ni = ieee80211_dup_bss(vap, wh->i_addr2);
426 +                               ni = ieee80211_dup_bss(vap, wh->i_addr2, 0);
427                                 if (ni == NULL)
428                                         return;
429  
430                                 IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, 
431                                 "%s: %p<%s> refcnt %d\n", __func__, ni, ether_sprintf(ni->ni_macaddr), 
432                                 ieee80211_node_refcnt(ni));
433 +                               tmpnode = 1;
434                         }
435                         IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_AUTH,
436                                 (seq + 1) | (IEEE80211_STATUS_ALG << 16));
437 +                       
438 +                       if (tmpnode)
439 +                               ieee80211_unref_node(&ni);
440                         return;
441                 }
442         }
443 @@ -1315,23 +1309,16 @@
444                 }
445                 /* always accept open authentication requests */
446                 if (ni == vap->iv_bss) {
447 -                       ni = ieee80211_dup_bss(vap, wh->i_addr2); 
448 +                       ni = ieee80211_dup_bss(vap, wh->i_addr2, 0); 
449                         if (ni == NULL)
450                                 return;
451  
452                         IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, 
453                         "%s: %p<%s> refcnt %d\n", __func__, ni, ether_sprintf(ni->ni_macaddr), 
454                         ieee80211_node_refcnt(ni));
455 -
456 -               } else if ((ni->ni_flags & IEEE80211_NODE_AREF) == 0)
457 -                       (void) ieee80211_ref_node(ni);
458 -               /*
459 -                * Mark the node as referenced to reflect that it's
460 -                * reference count has been bumped to ensure it remains
461 -                * after the transaction completes.
462 -                */
463 -               ni->ni_flags |= IEEE80211_NODE_AREF;
464 -
465 +                       tmpnode = 1;
466 +               }
467 +               
468                 IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_AUTH, seq + 1);
469                 IEEE80211_NOTE(vap, IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH,
470                         ni, "station authenticated (%s)", "open");
471 @@ -1341,6 +1328,8 @@
472                  */
473                 if (ni->ni_authmode != IEEE80211_AUTH_8021X)
474                         ieee80211_node_authorize(ni);
475 +               if (tmpnode)
476 +                       ieee80211_unref_node(&ni);
477                 break;
478  
479         case IEEE80211_M_STA:
480 @@ -1379,7 +1368,7 @@
481         int istmp;
482  
483         if (ni == vap->iv_bss) {
484 -               ni = ieee80211_tmp_node(vap, mac);
485 +               ni = ieee80211_dup_bss(vap, mac, 1);
486                 if (ni == NULL) {
487                         /* XXX msg */
488                         return;
489 @@ -1389,7 +1378,7 @@
490                 istmp = 0;
491         IEEE80211_SEND_MGMT(ni, subtype, arg);
492         if (istmp)
493 -               ieee80211_free_node(ni);
494 +               ieee80211_unref_node(&ni);
495  }
496  
497  static int
498 @@ -1505,7 +1494,7 @@
499                 switch (seq) {
500                 case IEEE80211_AUTH_SHARED_REQUEST:
501                         if (ni == vap->iv_bss) {
502 -                               ni = ieee80211_dup_bss(vap, wh->i_addr2);
503 +                               ni = ieee80211_dup_bss(vap, wh->i_addr2, 0);
504                                 if (ni == NULL) {
505                                         /* NB: no way to return an error */
506                                         return;
507 @@ -1516,17 +1505,8 @@
508                                 ieee80211_node_refcnt(ni));
509  
510                                 allocbs = 1;
511 -                       } else {
512 -                               if ((ni->ni_flags & IEEE80211_NODE_AREF) == 0)
513 -                                       (void) ieee80211_ref_node(ni);
514 -                               allocbs = 0;
515                         }
516 -                       /*
517 -                        * Mark the node as referenced to reflect that it's
518 -                        * reference count has been bumped to ensure it remains
519 -                        * after the transaction completes.
520 -                        */
521 -                       ni->ni_flags |= IEEE80211_NODE_AREF;
522 +
523                         ni->ni_rssi = rssi;
524                         ni->ni_rstamp = rstamp;
525                         ni->ni_last_rx = jiffies;
526 @@ -1620,14 +1600,13 @@
527         }
528         return;
529  bad:
530 -       /*
531 -        * Send an error response; but only when operating as an AP.
532 -        */
533 +       /* Send an error response; but only when operating as an AP. */
534         if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
535                 /* XXX hack to workaround calling convention */
536                 ieee80211_send_error(ni, wh->i_addr2, 
537                         IEEE80211_FC0_SUBTYPE_AUTH,
538                         (seq + 1) | (estatus<<16));
539 +               ieee80211_node_leave(ni);
540         } else if (vap->iv_opmode == IEEE80211_M_STA) {
541                 /*
542                  * Kick the state machine.  This short-circuits
543 @@ -2600,7 +2579,7 @@
544         u_int8_t *frm, *efrm;
545         u_int8_t *ssid, *rates, *xrates, *wpa, *rsn, *wme, *ath;
546         u_int8_t rate;
547 -       int reassoc, resp, allocbs;
548 +       int reassoc, resp, allocbs = 0;
549         u_int8_t qosinfo;
550  
551         wh = (struct ieee80211_frame *) skb->data;
552 @@ -3008,13 +2987,13 @@
553                                 ni = ieee80211_fakeup_adhoc_node(vap,
554                                         wh->i_addr2);
555                         } else {
556 -                               ni = ieee80211_tmp_node(vap, wh->i_addr2);
557 +                               ni = ieee80211_dup_bss(vap, wh->i_addr2, 1);
558                         }
559                         if (ni == NULL)
560                                 return;
561                         allocbs = 1;
562 -               } else
563 -                       allocbs = 0;
564 +               }
565 +
566                 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_INPUT, wh->i_addr2,
567                         "%s", "recv probe req");
568                 ni->ni_rssi = rssi;
569 @@ -3037,7 +3016,7 @@
570                          * Temporary node created just to send a
571                          * response, reclaim immediately
572                          */
573 -                       ieee80211_free_node(ni);
574 +                       ieee80211_unref_node(&ni);
575                 } else if (ath != NULL)
576                         ieee80211_saveath(ni, ath);
577                 break;
578 @@ -3067,6 +3046,9 @@
579                                         ni = vap->iv_xrvap->iv_bss;
580                                 else {
581                                         ieee80211_node_leave(ni);
582 +                                       /* This would be a stupid place to add a node to the table
583 +                                        * XR stuff needs work anyway
584 +                                        */
585                                         ieee80211_node_reset(ni, vap->iv_xrvap);
586                                 }
587                                 vap = vap->iv_xrvap;
588 diff -ur madwifi.old/net80211/ieee80211_linux.c madwifi.dev/net80211/ieee80211_linux.c
589 --- madwifi.old/net80211/ieee80211_linux.c      2007-05-18 13:19:16.000000000 +0200
590 +++ madwifi.dev/net80211/ieee80211_linux.c      2007-05-21 08:10:46.866753872 +0200
591 @@ -358,7 +358,7 @@
592          struct ieee80211_node *ni;
593          struct ieee80211_node_table *nt = (struct ieee80211_node_table *) &vap->iv_ic->ic_sta;
594  
595 -        //IEEE80211_NODE_LOCK(nt);                                                                               
596 +        /* IEEE80211_NODE_LOCK(nt); */
597          TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
598                  /* Assume each node needs 500 bytes */
599                  if (buf + space < p + 500)
600 @@ -376,7 +376,7 @@
601  
602                 }
603          }
604 -        //IEEE80211_NODE_UNLOCK(nt);                                                                             
605 +        /* IEEE80211_NODE_UNLOCK(nt); */
606          return (p - buf);
607  }
608  
609 diff -ur madwifi.old/net80211/ieee80211_linux.h madwifi.dev/net80211/ieee80211_linux.h
610 --- madwifi.old/net80211/ieee80211_linux.h      2007-05-04 15:45:58.000000000 +0200
611 +++ madwifi.dev/net80211/ieee80211_linux.h      2007-05-21 08:10:46.867753720 +0200
612 @@ -63,6 +63,12 @@
613  
614  #define        IEEE80211_RESCHEDULE    schedule
615  
616 +/* Locking */
617 +/* NB: beware, spin_is_locked() is not usefully defined for !(DEBUG || SMP)
618 + * because spinlocks do not exist in this configuration. Instead IRQs 
619 + * or pre-emption are simply disabled, as this is all that is needed.
620 + */
621 +
622  /*
623   * Beacon handler locking definitions.
624   * Beacon locking 
625 @@ -85,14 +91,14 @@
626  #define IEEE80211_LOCK(_ic)    spin_lock(&(_ic)->ic_comlock)
627  #define IEEE80211_UNLOCK(_ic)  spin_unlock(&(_ic)->ic_comlock)
628  
629 -/* NB: beware, spin_is_locked() is unusable for !SMP */
630 -#if defined(CONFIG_SMP)
631 +#if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked)
632  #define        IEEE80211_LOCK_ASSERT(_ic) \
633         KASSERT(spin_is_locked(&(_ic)->ic_comlock),("ieee80211com not locked!"))
634  #else
635  #define        IEEE80211_LOCK_ASSERT(_ic)
636  #endif
637  
638 +
639  #define IEEE80211_VAPS_LOCK_INIT(_ic, _name)           \
640         spin_lock_init(&(_ic)->ic_vapslock)
641  #define IEEE80211_VAPS_LOCK_DESTROY(_ic)
642 @@ -108,11 +114,10 @@
643  } while (0)
644  #define IEEE80211_VAPS_UNLOCK_IRQ_EARLY(_ic)   spin_unlock_irqrestore(&(_ic)->ic_vapslock, _vaps_lockflags)
645  
646 -
647 -/* NB: beware, spin_is_locked() is unusable for !SMP */
648 -#if defined(CONFIG_SMP)
649 +#if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked)
650  #define IEEE80211_VAPS_LOCK_ASSERT(_ic) \
651 -       KASSERT(spin_is_locked(&(_ic)->ic_vapslock),("ieee80211com_vaps not locked!"))
652 +       KASSERT(spin_is_locked(&(_ic)->ic_vapslock), \
653 +               ("ieee80211com_vaps not locked!"))
654  #else
655  #define IEEE80211_VAPS_LOCK_ASSERT(_ic)
656  #endif
657 @@ -121,29 +126,63 @@
658  /*
659   * Node locking definitions.
660   */
661 +#if 0
662 +
663  typedef spinlock_t ieee80211_node_lock_t;
664 -#define        IEEE80211_NODE_LOCK_INIT(_nt, _name)    spin_lock_init(&(_nt)->nt_nodelock)
665 -#define        IEEE80211_NODE_LOCK_DESTROY(_nt)
666 -#define        IEEE80211_NODE_LOCK(_nt)        spin_lock(&(_nt)->nt_nodelock)
667 -#define        IEEE80211_NODE_UNLOCK(_nt)      spin_unlock(&(_nt)->nt_nodelock)
668 -#define        IEEE80211_NODE_LOCK_BH(_nt)     spin_lock_bh(&(_nt)->nt_nodelock)
669 -#define        IEEE80211_NODE_UNLOCK_BH(_nt)   spin_unlock_bh(&(_nt)->nt_nodelock)
670 -#define        IEEE80211_NODE_LOCK_IRQ(_nt)    do {    \
671 +#define        IEEE80211_NODE_LOCK_INIT(_ni, _name)    spin_lock_init(&(_ni)->ni_nodelock)
672 +#define        IEEE80211_NODE_LOCK_DESTROY(_ni)
673 +#if 0  /* We should always be contesting in the same contexts */
674 +#define        IEEE80211_NODE_LOCK(_ni)        spin_lock(&(_ni)->ni_nodelock)
675 +#define        IEEE80211_NODE_UNLOCK(_ni)      spin_unlock(&(_ni)->ni_nodelock)
676 +#define        IEEE80211_NODE_LOCK_BH(_ni)     spin_lock_bh(&(_ni)->ni_nodelock)
677 +#define        IEEE80211_NODE_UNLOCK_BH(_ni)   spin_unlock_bh(&(_ni)->ni_nodelock)
678 +#endif
679 +#define        IEEE80211_NODE_LOCK_IRQ(_ni)    do {    \
680 +       unsigned long __node_lockflags;         \
681 +       spin_lock_irqsave(&(_ni)->ni_nodelock, __node_lockflags);
682 +#define        IEEE80211_NODE_UNLOCK_IRQ(_ni)          \
683 +       spin_unlock_irqrestore(&(_ni)->ni_nodelock, __node_lockflags); \
684 +} while(0)
685 +#define        IEEE80211_NODE_UNLOCK_IRQ_EARLY(_ni)            \
686 +       spin_unlock_irqrestore(&(_ni)->ni_nodelock, __node_lockflags);
687 +
688 +#if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked)
689 +#define        IEEE80211_NODE_LOCK_ASSERT(_nt) \
690 +       KASSERT(spin_is_locked(&(_ni)->ni_nodelock), \
691 +               ("802.11 node not locked!"))
692 +#else
693 +#define        IEEE80211_NODE_LOCK_ASSERT(_ni)
694 +#endif
695 +
696 +#endif /* node lock */
697 +
698 +/*
699 + * Node table locking definitions.
700 + */
701 +typedef spinlock_t ieee80211_node_table_lock_t;
702 +#define        IEEE80211_NODE_TABLE_LOCK_INIT(_nt, _name)      spin_lock_init(&(_nt)->nt_nodelock)
703 +#define        IEEE80211_NODE_TABLE_LOCK_DESTROY(_nt)
704 +#if 0  /* We should always be contesting in the same contexts */
705 +#define        IEEE80211_NODE_TABLE_LOCK(_nt)  spin_lock(&(_nt)->nt_nodelock)
706 +#define        IEEE80211_NODE_TABLE_UNLOCK(_nt)        spin_unlock(&(_nt)->nt_nodelock)
707 +#define        IEEE80211_NODE_TABLE_LOCK_BH(_nt)       spin_lock_bh(&(_nt)->nt_nodelock)
708 +#define        IEEE80211_NODE_TABLE_UNLOCK_BH(_nt)     spin_unlock_bh(&(_nt)->nt_nodelock)
709 +#endif
710 +#define        IEEE80211_NODE_TABLE_LOCK_IRQ(_nt)      do {    \
711         unsigned long __node_lockflags;         \
712         spin_lock_irqsave(&(_nt)->nt_nodelock, __node_lockflags);
713 -#define        IEEE80211_NODE_UNLOCK_IRQ(_nt)          \
714 +#define        IEEE80211_NODE_TABLE_UNLOCK_IRQ(_nt)            \
715         spin_unlock_irqrestore(&(_nt)->nt_nodelock, __node_lockflags); \
716  } while(0)
717 -#define        IEEE80211_NODE_UNLOCK_IRQ_EARLY(_nt)            \
718 +#define        IEEE80211_NODE_TABLE_UNLOCK_IRQ_EARLY(_nt)              \
719         spin_unlock_irqrestore(&(_nt)->nt_nodelock, __node_lockflags);
720  
721 -/* NB: beware, *_is_locked() are bogusly defined for UP+!PREEMPT */
722 -#if (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)) && defined(spinlock_is_locked)
723 -#define        IEEE80211_NODE_LOCK_ASSERT(_nt) \
724 -       KASSERT(spinlock_is_locked(&(_nt)->nt_nodelock), \
725 +#if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked)
726 +#define        IEEE80211_NODE_TABLE_LOCK_ASSERT(_nt) \
727 +       KASSERT(spin_is_locked(&(_nt)->nt_nodelock), \
728                 ("802.11 node table not locked!"))
729  #else
730 -#define        IEEE80211_NODE_LOCK_ASSERT(_nt)
731 +#define        IEEE80211_NODE_TABLE_LOCK_ASSERT(_nt)
732  #endif
733  
734  /*
735 @@ -163,8 +202,7 @@
736  #define        IEEE80211_SCAN_UNLOCK_IRQ_EARLY(_nt)            \
737         spin_unlock_irqrestore(&(_nt)->nt_scanlock, __scan_lockflags);
738  
739 -/* NB: beware, spin_is_locked() is unusable for !SMP */
740 -#if defined(CONFIG_SMP)
741 +#if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked)
742  #define        IEEE80211_SCAN_LOCK_ASSERT(_nt) \
743         KASSERT(spin_is_locked(&(_nt)->nt_scanlock), ("scangen not locked!"))
744  #else
745 @@ -182,8 +220,7 @@
746  #define        ACL_LOCK_BH(_as)                spin_lock_bh(&(_as)->as_lock)
747  #define        ACL_UNLOCK_BH(_as)              spin_unlock_bh(&(_as)->as_lock)
748  
749 -/* NB: beware, spin_is_locked() is unusable for !SMP */
750 -#if defined(CONFIG_SMP)
751 +#if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked)
752  #define        ACL_LOCK_ASSERT(_as) \
753         KASSERT(spin_is_locked(&(_as)->as_lock), ("ACL not locked!"))
754  #else
755 @@ -299,6 +336,7 @@
756   *                             is the last reference, otherwise 0
757   * ieee80211_node_refcnt       reference count for printing (only)
758   */
759 +typedef atomic_t ieee80211_node_ref_count_t; 
760  #define ieee80211_node_initref(_ni)    atomic_set(&(_ni)->ni_refcnt, 1)
761  #define ieee80211_node_incref(_ni)     atomic_inc(&(_ni)->ni_refcnt)
762  #define        ieee80211_node_decref(_ni)      atomic_dec(&(_ni)->ni_refcnt)
763 @@ -379,8 +417,8 @@
764  /* msecs_to_jiffies appeared in 2.6.7 and 2.4.29 */
765  #include <linux/delay.h>
766  #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \
767 -      LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7)) || \
768 -     LINUX_VERSION_CODE < KERNEL_VERSION(2,4,29)
769 +     LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7)) || \
770 +    LINUX_VERSION_CODE < KERNEL_VERSION(2,4,29)
771  
772  /* The following definitions and inline functions are
773   * copied from the kernel src, include/linux/jiffies.h */
774 diff -ur madwifi.old/net80211/ieee80211_node.c madwifi.dev/net80211/ieee80211_node.c
775 --- madwifi.old/net80211/ieee80211_node.c       2007-05-18 13:19:16.000000000 +0200
776 +++ madwifi.dev/net80211/ieee80211_node.c       2007-05-21 08:10:46.868753568 +0200
777 @@ -65,16 +65,17 @@
778  #define        IEEE80211_AID_ISSET(_vap, _b) \
779         ((_vap)->iv_aid_bitmap[IEEE80211_AID(_b) / 32] & (1 << (IEEE80211_AID(_b) % 32)))
780  
781 +static struct ieee80211_node *ieee80211_alloc_node(struct ieee80211vap *, const u_int8_t *);
782 +
783  static int ieee80211_sta_join1(struct ieee80211_node *);
784  
785 -static struct ieee80211_node *node_alloc(struct ieee80211_node_table *,
786 -       struct ieee80211vap *);
787 +static struct ieee80211_node *node_alloc(struct ieee80211vap *);
788  static void node_cleanup(struct ieee80211_node *);
789  static void node_free(struct ieee80211_node *);
790  static u_int8_t node_getrssi(const struct ieee80211_node *);
791  
792 -static void _ieee80211_free_node(struct ieee80211_node *);
793 -static void node_reclaim(struct ieee80211_node_table *, struct ieee80211_node*);
794 +static void _node_table_leave(struct ieee80211_node_table *, struct ieee80211_node *);
795 +static void _node_table_join(struct ieee80211_node_table *, struct ieee80211_node *);
796  
797  static void ieee80211_node_timeout(unsigned long);
798  
799 @@ -194,8 +195,7 @@
800  
801         ieee80211_node_table_reset(&ic->ic_sta, vap);
802         if (vap->iv_bss != NULL) {
803 -               ieee80211_free_node(vap->iv_bss);
804 -               vap->iv_bss = NULL;
805 +               ieee80211_unref_node(&vap->iv_bss);
806         }
807         if (vap->iv_aid_bitmap != NULL) {
808                 FREE(vap->iv_aid_bitmap, M_DEVBUF);
809 @@ -250,6 +250,7 @@
810         nbss->ni_txpower = obss->ni_txpower;
811         nbss->ni_vlan = obss->ni_vlan;
812         nbss->ni_rsn = obss->ni_rsn;
813 +       nbss->ni_rates = obss->ni_rates;
814         /* XXX statistics? */
815  }
816  
817 @@ -263,17 +264,17 @@
818                 "%s: creating ibss on channel %u\n", __func__,
819                 ieee80211_chan2ieee(ic, chan));
820  
821 -       /* Check to see if we already have a node for this mac */
822 +       /* Check to see if we already have a node for this mac 
823 +        * NB: we gain a node reference here
824 +        */
825         ni = ieee80211_find_node(&ic->ic_sta, vap->iv_myaddr);
826         if (ni == NULL) {
827 -               ni = ieee80211_alloc_node(&ic->ic_sta, vap, vap->iv_myaddr);
828 +               ni = ieee80211_alloc_node_table(vap, vap->iv_myaddr);
829                 if (ni == NULL) {
830                         /* XXX recovery? */
831                         return;
832                 }
833         }
834 -       else
835 -               ieee80211_free_node(ni);
836  
837         IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, "%s: %p<%s> refcnt %d\n",
838                 __func__, vap->iv_bss, ether_sprintf(vap->iv_bss->ni_macaddr),
839 @@ -339,7 +340,7 @@
840         else if (IEEE80211_IS_CHAN_QUARTER(chan))
841                 ni->ni_rates = ic->ic_sup_quarter_rates;
842  
843 -       (void) ieee80211_sta_join1(ieee80211_ref_node(ni));
844 +       (void) ieee80211_sta_join1(PASS_NODE(ni));
845  }
846  EXPORT_SYMBOL(ieee80211_create_ibss);
847  
848 @@ -363,9 +364,10 @@
849         /* XXX multi-bss wrong */
850         ieee80211_reset_erp(ic, ic->ic_curmode);
851  
852 -       ni = ieee80211_alloc_node(&ic->ic_sta, vap, vap->iv_myaddr);
853 +       ni = ieee80211_alloc_node_table(vap, vap->iv_myaddr);
854         KASSERT(ni != NULL, ("unable to setup inital BSS node"));
855         obss = vap->iv_bss;
856 +       /* New reference for caller */
857         vap->iv_bss = ieee80211_ref_node(ni);
858  
859         IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, "%s: new bss %p<%s> refcnt %d\n",
860 @@ -375,7 +377,8 @@
861         if (obss != NULL) {
862                 copy_bss(ni, obss);
863                 ni->ni_intval = ic->ic_lintval;
864 -               ieee80211_free_node(obss);
865 +               /* Caller's reference */
866 +               ieee80211_unref_node(&obss);
867         }
868  }
869  
870 @@ -581,7 +584,7 @@
871                 vap->iv_state == IEEE80211_S_RUN && ssid_equal(obss, selbs));
872         vap->iv_bss = selbs;
873         if (obss != NULL)
874 -               ieee80211_free_node(obss);
875 +               ieee80211_unref_node(&obss);
876         ic->ic_bsschan = selbs->ni_chan;
877         ic->ic_curchan = ic->ic_bsschan;
878         ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan);
879 @@ -638,21 +641,20 @@
880  
881         ni = ieee80211_find_node(&ic->ic_sta, se->se_macaddr);
882         if (ni == NULL) {
883 -               ni = ieee80211_alloc_node(&ic->ic_sta, vap, se->se_macaddr);
884 +               ni = ieee80211_alloc_node_table(vap, se->se_macaddr);
885                 if (ni == NULL) {
886                         IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, 
887                         "%s: Unable to allocate node for BSS: %s\n", __func__, 
888                         ether_sprintf(ni->ni_macaddr));
889                         return 0;
890                 }
891 -       } else
892 -               ieee80211_free_node(ni);
893 +       }
894  
895         /*
896          * Expand scan state into node's format.
897          * XXX may not need all this stuff
898          */
899 -       ni->ni_authmode = vap->iv_bss->ni_authmode;             /* inherit authmode from iv_bss */
900 +       ni->ni_authmode = vap->iv_bss->ni_authmode;     /* inherit authmode from iv_bss */
901         /* inherit the WPA setup as well (structure copy!) */
902         ni->ni_rsn = vap->iv_bss->ni_rsn; 
903         IEEE80211_ADDR_COPY(ni->ni_bssid, se->se_bssid);
904 @@ -686,9 +688,9 @@
905  
906         IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, 
907         "%s: %p<%s> refcnt %d\n", __func__, ni, ether_sprintf(ni->ni_macaddr), 
908 -       ieee80211_node_refcnt(ni)+1);
909 +       ieee80211_node_refcnt(ni));
910  
911 -       return ieee80211_sta_join1(ieee80211_ref_node(ni));
912 +       return ieee80211_sta_join1(PASS_NODE(ni));
913  }
914  EXPORT_SYMBOL(ieee80211_sta_join);
915  
916 @@ -700,15 +702,13 @@
917  ieee80211_sta_leave(struct ieee80211_node *ni)
918  {
919         struct ieee80211vap *vap = ni->ni_vap;
920 -       struct ieee80211com *ic = vap->iv_ic;
921  
922         /* WDS/Repeater: Stop software beacon timer for STA */
923         if (vap->iv_opmode == IEEE80211_M_STA &&
924             vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS) {
925                 del_timer(&vap->iv_swbmiss);
926         }
927 -
928 -       ic->ic_node_cleanup(ni);
929 +       
930         ieee80211_notify_node_leave(ni);
931  }
932  
933 @@ -717,11 +717,11 @@
934   */
935  
936  static void
937 -ieee80211_node_table_init(struct ieee80211com *ic,
938 -       struct ieee80211_node_table *nt,        const char *name, int inact)
939 +ieee80211_node_table_init(struct ieee80211com *ic, struct ieee80211_node_table *nt,
940 +               const char *name, int inact)
941  {
942         nt->nt_ic = ic;
943 -       IEEE80211_NODE_LOCK_INIT(nt, ic->ic_dev->name);
944 +       IEEE80211_NODE_TABLE_LOCK_INIT(nt, ic->ic_dev->name);
945         IEEE80211_SCAN_LOCK_INIT(nt, ic->ic_dev->name);
946         TAILQ_INIT(&nt->nt_node);
947         nt->nt_name = name;
948 @@ -733,11 +733,31 @@
949         mod_timer(&nt->nt_wds_aging_timer, jiffies + HZ * WDS_AGING_TIMER_VAL);
950  }
951  
952 +static __inline void _node_table_join(struct ieee80211_node_table *nt, struct ieee80211_node *ni) {
953 +       IEEE80211_NODE_TABLE_LOCK_ASSERT(nt);
954 +
955 +       ni->ni_table = nt;
956 +       TAILQ_INSERT_TAIL(&nt->nt_node, ieee80211_ref_node(ni), ni_list);
957 +       LIST_INSERT_HEAD(&nt->nt_hash[IEEE80211_NODE_HASH(ni->ni_macaddr)], ni, ni_hash);
958 +}
959 +
960 +static __inline void _node_table_leave(struct ieee80211_node_table *nt, struct ieee80211_node *ni) {
961 +       struct ieee80211_node *hni;
962 +       IEEE80211_NODE_TABLE_LOCK_ASSERT(nt);
963 +       
964 +       TAILQ_REMOVE(&nt->nt_node, ni, ni_list);
965 +       LIST_FOREACH(hni, &nt->nt_hash[IEEE80211_NODE_HASH(ni->ni_macaddr)], ni_hash) {
966 +               LIST_REMOVE(ni, ni_hash);
967 +       }
968 +       ni->ni_table = NULL;
969 +       _ieee80211_unref_node(ni);
970 +}
971 +
972  /* This is overridden by ath_node_alloc in ath/if_ath.c, and so
973 - * should never get called
974 + * should never get called.
975   */
976  static struct ieee80211_node *
977 -node_alloc(struct ieee80211_node_table *nt, struct ieee80211vap *vap)
978 +node_alloc(struct ieee80211vap *vap)
979  {
980         struct ieee80211_node *ni;
981  
982 @@ -776,13 +796,6 @@
983                         IEEE80211_UNLOCK_IRQ(ni->ni_ic);
984                 }
985         }
986 -       /*
987 -        * Clear AREF flag that marks the authorization refcnt bump
988 -        * has happened.  This is probably not needed as the node
989 -        * should always be removed from the table so not found but
990 -        * do it just in case.
991 -        */
992 -       ni->ni_flags &= ~IEEE80211_NODE_AREF;
993  
994         /*
995          * Drain power save queue and, if needed, clear TIM.
996 @@ -791,10 +804,7 @@
997                 vap->iv_set_tim(ni, 0);
998  
999         ni->ni_associd = 0;
1000 -       if (ni->ni_challenge != NULL) {
1001 -               FREE(ni->ni_challenge, M_DEVBUF);
1002 -               ni->ni_challenge = NULL;
1003 -       }
1004 +       
1005         /*
1006          * Preserve SSID, WPA, and WME ie's so the bss node is
1007          * reusable during a re-auth/re-assoc state transition.
1008 @@ -819,9 +829,16 @@
1009  static void
1010  node_free(struct ieee80211_node *ni)
1011  {
1012 +#if 0
1013 +       /* We should 'cleanup' and then free'ing should be done automatically on decref */
1014         struct ieee80211com *ic = ni->ni_ic;
1015  
1016         ic->ic_node_cleanup(ni);
1017 +#endif 
1018 +       KASSERT(ieee80211_node_refcnt(ni) == 0, ("node being free whilst still referenced"));
1019 +
1020 +       if (ni->ni_challenge != NULL) 
1021 +               FREE(ni->ni_challenge, M_DEVBUF);
1022         if (ni->ni_wpa_ie != NULL)
1023                 FREE(ni->ni_wpa_ie, M_DEVBUF);
1024         if (ni->ni_rsn_ie != NULL)
1025 @@ -831,6 +848,7 @@
1026         if (ni->ni_ath_ie != NULL)
1027                 FREE(ni->ni_ath_ie, M_DEVBUF);
1028         IEEE80211_NODE_SAVEQ_DESTROY(ni);
1029 +       
1030         FREE(ni, M_80211_NODE);
1031  }
1032  
1033 @@ -847,55 +865,70 @@
1034   * This interface is not intended for general use, it is
1035   * used by the routines below to create entries with a
1036   * specific purpose.
1037 + * Dont assume a BSS?
1038   */
1039  struct ieee80211_node *
1040 -ieee80211_alloc_node(struct ieee80211_node_table *nt,
1041 -       struct ieee80211vap *vap, const u_int8_t *macaddr)
1042 +ieee80211_alloc_node_table(struct ieee80211vap *vap, 
1043 +       const u_int8_t *macaddr)
1044  {
1045 -       struct ieee80211com *ic = nt->nt_ic;
1046 +       struct ieee80211com *ic = vap->iv_ic;
1047 +       struct ieee80211_node_table *nt = &ic->ic_sta;
1048         struct ieee80211_node *ni;
1049 -       int hash;
1050  
1051 -       ni = ic->ic_node_alloc(nt, vap);
1052 -       if (ni == NULL) {
1053 -               /* XXX msg */
1054 -               vap->iv_stats.is_rx_nodealloc++;
1055 -               return NULL;
1056 -       }
1057 +       ni = ieee80211_alloc_node(vap, macaddr);
1058 +       if (ni != NULL) {
1059 +               ni->ni_inact = ni->ni_inact_reload = nt->nt_inact_init;
1060  
1061 -       IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
1062 -               "%s: %p<%s> in %s table, refcnt %d\n", __func__, ni,
1063 -               ether_sprintf(macaddr), nt->nt_name,
1064 -               ieee80211_node_refcnt(ni)+1);
1065 +               WME_UAPSD_NODE_TRIGSEQINIT(ni);
1066 +               IEEE80211_NODE_SAVEQ_INIT(ni, "unknown");
1067  
1068 -       IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr);
1069 -       hash = IEEE80211_NODE_HASH(macaddr);
1070 -       ieee80211_node_initref(ni);             /* mark referenced */
1071 -       ni->ni_chan = IEEE80211_CHAN_ANYC;
1072 -       ni->ni_authmode = IEEE80211_AUTH_OPEN;
1073 -       ni->ni_txpower = ic->ic_txpowlimit;     /* max power */
1074 -       ieee80211_crypto_resetkey(vap, &ni->ni_ucastkey, IEEE80211_KEYIX_NONE);
1075 -       ni->ni_inact_reload = nt->nt_inact_init;
1076 -       ni->ni_inact = ni->ni_inact_reload;
1077 -       ni->ni_ath_defkeyindex = IEEE80211_INVAL_DEFKEY;
1078 -       ni->ni_rxkeyoff = 0;
1079 -       IEEE80211_NODE_SAVEQ_INIT(ni, "unknown");
1080 +               IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
1081 +               _node_table_join(nt, ni);
1082 +               IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
1083 +       }
1084  
1085 -       IEEE80211_NODE_LOCK_IRQ(nt);
1086 -       ni->ni_vap = vap;
1087 -       ni->ni_ic = ic;
1088 -       ni->ni_table = nt;
1089 -       TAILQ_INSERT_TAIL(&nt->nt_node, ni, ni_list);
1090 -       LIST_INSERT_HEAD(&nt->nt_hash[hash], ni, ni_hash);
1091 -       ni->ni_rxfrag = NULL;
1092 -       ni->ni_challenge = NULL;
1093 -       IEEE80211_NODE_UNLOCK_IRQ(nt);
1094 +       return ni;
1095 +}
1096 +EXPORT_SYMBOL(ieee80211_alloc_node_table);
1097 +
1098 +/* Allocate a node structure and initialise specialised structures
1099 + * This function does not add the node to the node table, thus this
1100 + * node will not be found using ieee80211_find_*node.
1101 + * This is useful when sending one off errors or request denials.
1102 + */
1103 +static struct ieee80211_node *
1104 +ieee80211_alloc_node(struct ieee80211vap *vap, const u_int8_t *macaddr)
1105 +{
1106 +       struct ieee80211com *ic = vap->iv_ic;
1107 +       struct ieee80211_node *ni;
1108 +       
1109 +       /* This always allocates zeroed memoery */
1110 +       ni = ic->ic_node_alloc(vap);
1111 +       if (ni != NULL) {
1112 +               IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, 
1113 +               "%s: %p<%s> refcnt %d\n", __func__, ni, ether_sprintf(macaddr), 
1114 +               ieee80211_node_refcnt(ni)+1);
1115  
1116 -       WME_UAPSD_NODE_TRIGSEQINIT(ni);
1117 +               ieee80211_node_initref(ni);             /* mark referenced */
1118 +               
1119 +               IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr);
1120 +               
1121 +               ni->ni_chan = IEEE80211_CHAN_ANYC;
1122 +               ni->ni_authmode = IEEE80211_AUTH_OPEN;
1123 +               ni->ni_txpower = ic->ic_txpowlimit;
1124 +               
1125 +               ieee80211_crypto_resetkey(vap, &ni->ni_ucastkey,
1126 +                       IEEE80211_KEYIX_NONE);
1127 +               ni->ni_ath_defkeyindex = IEEE80211_INVAL_DEFKEY;
1128  
1129 +               ni->ni_vap = vap;
1130 +               ni->ni_ic = ic;
1131 +       } else {
1132 +               /* XXX msg */
1133 +               vap->iv_stats.is_rx_nodealloc++;
1134 +       }
1135         return ni;
1136  }
1137 -EXPORT_SYMBOL(ieee80211_alloc_node);
1138  
1139  /* Add wds address to the node table */
1140  int
1141 @@ -917,11 +950,11 @@
1142                 wds->wds_agingcount = WDS_AGING_COUNT;
1143         hash = IEEE80211_NODE_HASH(macaddr);
1144         IEEE80211_ADDR_COPY(wds->wds_macaddr, macaddr);
1145 -       ieee80211_ref_node(ni);         /* Reference node */
1146 -       wds->wds_ni = ni;
1147 -       IEEE80211_NODE_LOCK_IRQ(nt);
1148 +       
1149 +       IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
1150 +       wds->wds_ni = ieee80211_ref_node(ni);
1151         LIST_INSERT_HEAD(&nt->nt_wds_hash[hash], wds, wds_hash);
1152 -       IEEE80211_NODE_UNLOCK_IRQ(nt);
1153 +       IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
1154         return 0;
1155  }
1156  EXPORT_SYMBOL(ieee80211_add_wds_addr);
1157 @@ -934,22 +967,19 @@
1158         struct ieee80211_wds_addr *wds, *twds;
1159  
1160         hash = IEEE80211_NODE_HASH(macaddr);
1161 -       IEEE80211_NODE_LOCK_IRQ(nt);
1162 +       IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
1163         LIST_FOREACH_SAFE(wds, &nt->nt_wds_hash[hash], wds_hash, twds) {
1164                 if (IEEE80211_ADDR_EQ(wds->wds_macaddr, macaddr)) {
1165 -                       if (ieee80211_node_dectestref(wds->wds_ni)) {
1166 -                               _ieee80211_free_node(wds->wds_ni);
1167 -                               LIST_REMOVE(wds, wds_hash);
1168 -                               FREE(wds, M_80211_WDS);
1169 -                               break;
1170 -                       }
1171 +                       LIST_REMOVE(wds, wds_hash);
1172 +                       ieee80211_unref_node(&wds->wds_ni);
1173 +                       FREE(wds, M_80211_WDS);
1174 +                       break;
1175                 }
1176         }
1177 -       IEEE80211_NODE_UNLOCK_IRQ(nt);
1178 +       IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
1179  }
1180  EXPORT_SYMBOL(ieee80211_remove_wds_addr);
1181  
1182 -
1183  /* Remove node references from wds table */
1184  void
1185  ieee80211_del_wds_node(struct ieee80211_node_table *nt, struct ieee80211_node *ni)
1186 @@ -957,19 +987,17 @@
1187         int hash;
1188         struct ieee80211_wds_addr *wds, *twds;
1189  
1190 -       IEEE80211_NODE_LOCK_IRQ(nt);
1191 +       IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
1192         for (hash = 0; hash < IEEE80211_NODE_HASHSIZE; hash++) {
1193                 LIST_FOREACH_SAFE(wds, &nt->nt_wds_hash[hash], wds_hash, twds) {
1194                         if (wds->wds_ni == ni) {
1195 -                               if (ieee80211_node_dectestref(ni)) {
1196 -                                       _ieee80211_free_node(ni);
1197 -                                       LIST_REMOVE(wds, wds_hash);
1198 -                                       FREE(wds, M_80211_WDS);
1199 -                               }
1200 +                               LIST_REMOVE(wds, wds_hash);
1201 +                               ieee80211_unref_node(&wds->wds_ni);
1202 +                               FREE(wds, M_80211_WDS);
1203                         }
1204                 }
1205         }
1206 -       IEEE80211_NODE_UNLOCK_IRQ(nt);
1207 +       IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
1208  }
1209  EXPORT_SYMBOL(ieee80211_del_wds_node);
1210  
1211 @@ -980,88 +1008,46 @@
1212         int hash;
1213         struct ieee80211_wds_addr *wds, *twds;
1214  
1215 -       IEEE80211_NODE_LOCK_IRQ(nt);
1216 +       IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
1217         for (hash = 0; hash < IEEE80211_NODE_HASHSIZE; hash++) {
1218                 LIST_FOREACH_SAFE(wds, &nt->nt_wds_hash[hash], wds_hash, twds) {
1219                         if (wds->wds_agingcount != WDS_AGING_STATIC) {
1220                                 if (!wds->wds_agingcount) {
1221 -                                       if (ieee80211_node_dectestref(wds->wds_ni)) {
1222 -                                               _ieee80211_free_node(wds->wds_ni);  
1223 -                                               LIST_REMOVE(wds, wds_hash);
1224 -                                               FREE(wds, M_80211_WDS);
1225 -                                       }
1226 +                                       LIST_REMOVE(wds, wds_hash);
1227 +                                       ieee80211_unref_node(&wds->wds_ni);  
1228 +                                       FREE(wds, M_80211_WDS);
1229                                 } else
1230                                         wds->wds_agingcount--;
1231                         }
1232                 }
1233         }
1234 -       IEEE80211_NODE_UNLOCK_IRQ(nt);
1235 +       IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
1236         mod_timer(&nt->nt_wds_aging_timer, jiffies + HZ * WDS_AGING_TIMER_VAL);
1237  }
1238  
1239  
1240  /*
1241 - * Craft a temporary node suitable for sending a management frame
1242 - * to the specified station.  We craft only as much state as we
1243 - * need to do the work since the node will be immediately reclaimed
1244 - * once the send completes.
1245 - */
1246 -struct ieee80211_node *
1247 -ieee80211_tmp_node(struct ieee80211vap *vap, const u_int8_t *macaddr)
1248 -{
1249 -       struct ieee80211com *ic = vap->iv_ic;
1250 -       struct ieee80211_node *ni;
1251 -
1252 -       ni = ic->ic_node_alloc(&ic->ic_sta,vap);
1253 -       if (ni != NULL) {
1254 -               IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, 
1255 -               "%s: %p<%s> refcnt %d\n", __func__, ni, ether_sprintf(macaddr), 
1256 -               ieee80211_node_refcnt(ni)+1);
1257 -
1258 -               IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr);
1259 -               IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_bss->ni_bssid);
1260 -               ieee80211_node_initref(ni);             /* mark referenced */
1261 -               ni->ni_txpower = vap->iv_bss->ni_txpower;
1262 -               ni->ni_vap = vap;
1263 -               /* NB: required by ieee80211_fix_rate */
1264 -               ieee80211_node_set_chan(ic, ni);
1265 -               ieee80211_crypto_resetkey(vap, &ni->ni_ucastkey,
1266 -                       IEEE80211_KEYIX_NONE);
1267 -               /* XXX optimize away */
1268 -               IEEE80211_NODE_SAVEQ_INIT(ni, "unknown");
1269 -
1270 -               ni->ni_table = NULL;            /* NB: pedantic */
1271 -               ni->ni_ic = ic;
1272 -               ni->ni_rxfrag = NULL;
1273 -               ni->ni_challenge = NULL;
1274 -       } else {
1275 -               /* XXX msg */
1276 -               vap->iv_stats.is_rx_nodealloc++;
1277 -       }
1278 -       return ni;
1279 -}
1280 -
1281 -/*
1282   * Add the specified station to the station table.
1283   */
1284  struct ieee80211_node *
1285 -ieee80211_dup_bss(struct ieee80211vap *vap, const u_int8_t *macaddr)
1286 +ieee80211_dup_bss(struct ieee80211vap *vap, const u_int8_t *macaddr, 
1287 +               unsigned char tmp)
1288  {
1289 -       struct ieee80211com *ic = vap->iv_ic;
1290         struct ieee80211_node *ni;
1291 +       
1292 +       /* FIXME: Hack */
1293 +       if (tmp)
1294 +               ni = ieee80211_alloc_node(vap, macaddr);
1295 +       else
1296 +               ni = ieee80211_alloc_node_table(vap, macaddr);
1297  
1298 -       ni = ieee80211_alloc_node(&ic->ic_sta, vap, macaddr);
1299         if (ni != NULL) {
1300 -               /*
1301 -                * Inherit from iv_bss.
1302 -                */
1303 -               ni->ni_authmode = vap->iv_bss->ni_authmode;
1304 -               ni->ni_txpower = vap->iv_bss->ni_txpower;
1305 -               ni->ni_vlan = vap->iv_bss->ni_vlan;     /* XXX?? */
1306 +               copy_bss(ni, vap->iv_bss);
1307                 IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_bss->ni_bssid);
1308 -               ieee80211_node_set_chan(ic, ni);
1309 -               ni->ni_rsn = vap->iv_bss->ni_rsn;
1310 -               ni->ni_rxfrag = NULL;
1311 +               /* Do this only for nodes that already have a BSS. Otherwise
1312 +                * ic_bsschan is not set and we get a KASSERT failure.
1313 +                * Required by ieee80211_fix_rate */
1314 +               ieee80211_node_set_chan(vap->iv_ic, ni);
1315         }
1316         return ni;
1317  }
1318 @@ -1069,19 +1055,16 @@
1319  static struct ieee80211_node *
1320  _ieee80211_find_wds_node(struct ieee80211_node_table *nt, const u_int8_t *macaddr)
1321  {
1322 -       struct ieee80211_node *ni;
1323         struct ieee80211_wds_addr *wds;
1324         int hash;
1325 -       IEEE80211_NODE_LOCK_ASSERT(nt);
1326 +       IEEE80211_NODE_TABLE_LOCK_ASSERT(nt);
1327  
1328         hash = IEEE80211_NODE_HASH(macaddr);
1329         LIST_FOREACH(wds, &nt->nt_wds_hash[hash], wds_hash) {
1330                 if (IEEE80211_ADDR_EQ(wds->wds_macaddr, macaddr)) {
1331 -                       ni = wds->wds_ni;
1332                         if (wds->wds_agingcount != WDS_AGING_STATIC)
1333                                 wds->wds_agingcount = WDS_AGING_COUNT; /* reset the aging count */
1334 -                       ieee80211_ref_node(ni);
1335 -                       return ni;
1336 +                       return ieee80211_ref_node(wds->wds_ni);
1337                 }
1338         }
1339         return NULL;
1340 @@ -1099,7 +1082,7 @@
1341         int hash;
1342         struct ieee80211_wds_addr *wds;
1343  
1344 -       IEEE80211_NODE_LOCK_ASSERT(nt);
1345 +       IEEE80211_NODE_TABLE_LOCK_ASSERT(nt);
1346  
1347         hash = IEEE80211_NODE_HASH(macaddr);
1348         LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) {
1349 @@ -1120,9 +1103,7 @@
1350            nodes. */
1351         LIST_FOREACH(wds, &nt->nt_wds_hash[hash], wds_hash) {
1352                 if (IEEE80211_ADDR_EQ(wds->wds_macaddr, macaddr)) {
1353 -                       ni = wds->wds_ni;
1354 -                       ieee80211_ref_node(ni);
1355 -                       return ni;
1356 +                       return ieee80211_ref_node(wds->wds_ni);
1357                 }
1358         }
1359         return NULL;
1360 @@ -1137,9 +1118,9 @@
1361  {
1362         struct ieee80211_node *ni;
1363  
1364 -       IEEE80211_NODE_LOCK_IRQ(nt);
1365 +       IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
1366         ni = _ieee80211_find_wds_node(nt, macaddr);
1367 -       IEEE80211_NODE_UNLOCK_IRQ(nt);
1368 +       IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
1369         return ni;
1370  }
1371  EXPORT_SYMBOL(ieee80211_find_wds_node);
1372 @@ -1154,9 +1135,9 @@
1373  {
1374         struct ieee80211_node *ni;
1375  
1376 -       IEEE80211_NODE_LOCK_IRQ(nt);
1377 +       IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
1378         ni = _ieee80211_find_node(nt, macaddr);
1379 -       IEEE80211_NODE_UNLOCK_IRQ(nt);
1380 +       IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
1381         return ni;
1382  }
1383  #ifdef IEEE80211_DEBUG_REFCNT
1384 @@ -1179,7 +1160,7 @@
1385  {
1386         struct ieee80211_node *ni;
1387  
1388 -       ni = ieee80211_dup_bss(vap, macaddr);
1389 +       ni = ieee80211_dup_bss(vap, macaddr, 0);
1390         if (ni != NULL) {
1391                 /* XXX no rate negotiation; just dup */
1392                 ni->ni_rates = vap->iv_bss->ni_rates;
1393 @@ -1202,14 +1183,13 @@
1394   * driver has an opportunity to setup it's private state.
1395   */
1396  struct ieee80211_node *
1397 -ieee80211_add_neighbor(struct ieee80211vap *vap,       const struct ieee80211_frame *wh,
1398 +ieee80211_add_neighbor(struct ieee80211vap *vap, const struct ieee80211_frame *wh,
1399         const struct ieee80211_scanparams *sp)
1400  {
1401         struct ieee80211com *ic = vap->iv_ic;
1402         struct ieee80211_node *ni;
1403  
1404 -       ni = ieee80211_dup_bss(vap, wh->i_addr2);       /* XXX alloc_node? */
1405 -       /* TODO: not really putting itself in a table */
1406 +       ni = ieee80211_dup_bss(vap, wh->i_addr2, 1);
1407         if (ni != NULL) {
1408                 ni->ni_esslen = sp->ssid[1];
1409                 memcpy(ni->ni_essid, sp->ssid + 2, sp->ssid[1]);
1410 @@ -1284,12 +1264,12 @@
1411         /* XXX check ic_bss first in station mode */
1412         /* XXX 4-address frames? */
1413         nt = &ic->ic_sta;
1414 -       IEEE80211_NODE_LOCK_IRQ(nt);
1415 +       IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
1416         if (IS_CTL(wh) && !IS_PSPOLL(wh) /*&& !IS_RTS(ah)*/)
1417                 ni = _ieee80211_find_node(nt, wh->i_addr1);
1418         else
1419                 ni = _ieee80211_find_node(nt, wh->i_addr2);
1420 -       IEEE80211_NODE_UNLOCK_IRQ(nt);
1421 +       IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
1422  
1423         return ni;
1424  #undef IS_PSPOLL
1425 @@ -1326,9 +1306,9 @@
1426  
1427         /* XXX can't hold lock across dup_bss due to recursive locking */
1428         nt = &vap->iv_ic->ic_sta;
1429 -       IEEE80211_NODE_LOCK_IRQ(nt);
1430 +       IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
1431         ni = _ieee80211_find_node(nt, mac);
1432 -       IEEE80211_NODE_UNLOCK_IRQ(nt);
1433 +       IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
1434  
1435         if (ni == NULL) {
1436                 if (vap->iv_opmode == IEEE80211_M_IBSS ||
1437 @@ -1355,11 +1335,9 @@
1438  EXPORT_SYMBOL(ieee80211_find_txnode);
1439  #endif
1440  
1441 -/* Caller must lock the IEEE80211_NODE_LOCK
1442 - *
1443 - * Context: hwIRQ, softIRQ and process context
1444 +/* Context: hwIRQ, softIRQ and process context
1445   */
1446 -static void
1447 +void
1448  _ieee80211_free_node(struct ieee80211_node *ni)
1449  {
1450         struct ieee80211vap *vap = ni->ni_vap;
1451 @@ -1373,117 +1351,36 @@
1452  
1453         if (vap->iv_aid_bitmap != NULL)
1454                 IEEE80211_AID_CLR(vap, ni->ni_associd);
1455 -       if (nt != NULL) {
1456 -               TAILQ_REMOVE(&nt->nt_node, ni, ni_list);
1457 -               LIST_REMOVE(ni, ni_hash);
1458 -       }
1459 +
1460         vap->iv_ic->ic_node_free(ni);
1461  }
1462 +EXPORT_SYMBOL(_ieee80211_free_node);
1463  
1464 -void
1465 -#ifdef IEEE80211_DEBUG_REFCNT
1466 -ieee80211_free_node_debug(struct ieee80211_node *ni, const char *func, int line)
1467 -#else
1468 -ieee80211_free_node(struct ieee80211_node *ni)
1469 -#endif
1470 +static void _reset_node(void *arg, struct ieee80211_node *ni)
1471  {
1472 -       struct ieee80211_node_table *nt = ni->ni_table;
1473 -       struct ieee80211com *ic = ni->ni_ic;
1474 +       if (ni->ni_associd != 0) {
1475 +               struct ieee80211vap *vap = ni->ni_vap;
1476  
1477 -#ifdef IEEE80211_DEBUG_REFCNT
1478 -       IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_NODE,
1479 -               "%s (%s:%u) %p<%s> refcnt %d\n", __func__, func, line, ni,
1480 -                ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni) - 1);
1481 -#endif
1482 -       /*
1483 -        * XXX: may need to lock out the following race. we dectestref
1484 -        *      and determine it's time to free the node. between the if()
1485 -        *      and lock, we take an rx intr to receive a frame from this
1486 -        *      node. the rx path (tasklet or intr) bumps this node's
1487 -        *      refcnt and xmits a response frame. eventually that response
1488 -        *      will get reaped, and the reaping code will attempt to use
1489 -        *      the node. the code below will delete the node prior
1490 -        *      to the reap and we could get a crash.
1491 -        *
1492 -        *      as a stopgap before delving deeper, lock intrs to
1493 -        *      prevent this case.
1494 -        */
1495 -       IEEE80211_LOCK_IRQ(ic);
1496 -       if (ieee80211_node_dectestref(ni)) {
1497 -               /*
1498 -                * Beware; if the node is marked gone then it's already
1499 -                * been removed from the table and we cannot assume the
1500 -                * table still exists.  Regardless, there's no need to lock
1501 -                * the table.
1502 -                */
1503 -               if (ni->ni_table != NULL) {
1504 -                       IEEE80211_NODE_LOCK(nt);
1505 -                       _ieee80211_free_node(ni);
1506 -                       IEEE80211_NODE_UNLOCK(nt);
1507 -               } else
1508 -                       _ieee80211_free_node(ni);
1509 +               if (vap->iv_auth->ia_node_leave != NULL)
1510 +                       vap->iv_auth->ia_node_leave(ni);
1511 +               if (vap->iv_aid_bitmap != NULL)
1512 +                       IEEE80211_AID_CLR(vap, ni->ni_associd);
1513         }
1514 -       IEEE80211_UNLOCK_IRQ(ic);
1515 -}
1516 -#ifdef IEEE80211_DEBUG_REFCNT
1517 -EXPORT_SYMBOL(ieee80211_free_node_debug);
1518 -#else
1519 -EXPORT_SYMBOL(ieee80211_free_node);
1520 -#endif
1521 -
1522 -/*
1523 - * Reclaim a node.  If this is the last reference count then
1524 - * do the normal free work.  Otherwise remove it from the node
1525 - * table and mark it gone by clearing the back-reference.
1526 - */
1527 -static void
1528 -node_reclaim(struct ieee80211_node_table *nt, struct ieee80211_node *ni)
1529 -{
1530  
1531 -       IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_NODE,
1532 -               "%s: remove %p<%s> from %s table, refcnt %d\n",
1533 -               __func__, ni, ether_sprintf(ni->ni_macaddr),
1534 -               nt->nt_name, ieee80211_node_refcnt(ni)-1);
1535 -       if (!ieee80211_node_dectestref(ni)) {
1536 -               /*
1537 -                * Other references are present, just remove the
1538 -                * node from the table so it cannot be found.  When
1539 -                * the references are dropped storage will be
1540 -                * reclaimed.  This normally only happens for ic_bss.
1541 -                */
1542 -               TAILQ_REMOVE(&nt->nt_node, ni, ni_list);
1543 -               LIST_REMOVE(ni, ni_hash);
1544 -               ni->ni_table = NULL;            /* clear reference */
1545 -       } else
1546 -               _ieee80211_free_node(ni);
1547 +       ieee80211_node_leave(ni);
1548  }
1549  
1550  static void
1551  ieee80211_node_table_reset(struct ieee80211_node_table *nt,
1552 -       struct ieee80211vap *match)
1553 +       struct ieee80211vap *vap)
1554  {
1555 -       struct ieee80211_node *ni, *next;
1556 -
1557 -       IEEE80211_NODE_LOCK_IRQ(nt);
1558 -       TAILQ_FOREACH_SAFE(ni, &nt->nt_node, ni_list, next) {
1559 -               if (match != NULL && ni->ni_vap != match)
1560 -                       continue;
1561 -               if (ni->ni_associd != 0) {
1562 -                       struct ieee80211vap *vap = ni->ni_vap;
1563 -
1564 -                       if (vap->iv_auth->ia_node_leave != NULL)
1565 -                               vap->iv_auth->ia_node_leave(ni);
1566 -                       if (vap->iv_aid_bitmap != NULL)
1567 -                               IEEE80211_AID_CLR(vap, ni->ni_associd);
1568 -               }
1569 -               node_reclaim(nt, ni);
1570 -       }
1571 -       IEEE80211_NODE_UNLOCK_IRQ(nt);
1572 +       ieee80211_iterate_dev_nodes(vap->iv_dev, nt, _reset_node, NULL);
1573  }
1574  
1575  static void
1576  ieee80211_node_table_cleanup(struct ieee80211_node_table *nt)
1577  {
1578 +       struct ieee80211com *ic = nt->nt_ic;
1579         struct ieee80211_node *ni, *next;
1580  
1581         TAILQ_FOREACH_SAFE(ni, &nt->nt_node, ni_list, next) {
1582 @@ -1495,11 +1392,11 @@
1583                         if (vap->iv_aid_bitmap != NULL)
1584                                 IEEE80211_AID_CLR(vap, ni->ni_associd);
1585                 }
1586 -               node_reclaim(nt, ni);
1587 +               ic->ic_node_cleanup(ni);
1588         }
1589         del_timer(&nt->nt_wds_aging_timer);
1590         IEEE80211_SCAN_LOCK_DESTROY(nt);
1591 -       IEEE80211_NODE_LOCK_DESTROY(nt);
1592 +       IEEE80211_NODE_TABLE_LOCK_DESTROY(nt);
1593  }
1594  
1595  /*
1596 @@ -1527,19 +1424,22 @@
1597         IEEE80211_SCAN_LOCK_IRQ(nt); 
1598         gen = ++nt->nt_scangen;
1599  restart:
1600 -       IEEE80211_NODE_LOCK_IRQ(nt);
1601 +       IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
1602         TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
1603                 if (ni->ni_scangen == gen)      /* previously handled */
1604                         continue;
1605 +               /* Temporary entries should no longer be in the node table */
1606                 /*
1607                  * Ignore entries for which have yet to receive an
1608                  * authentication frame.  These are transient and
1609                  * will be reclaimed when the last reference to them
1610                  * goes away (when frame xmits complete).
1611                  */
1612 -               if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
1613 -                   (ni->ni_flags & IEEE80211_NODE_AREF) == 0)
1614 -                       continue;
1615 +               /*
1616 +                *if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
1617 +                *   (ni->ni_flags & IEEE80211_NODE_AREF) == 0)
1618 +                *      continue;
1619 +                */
1620                 ni->ni_scangen = gen;
1621                 /*
1622                  * Free fragment if not needed anymore
1623 @@ -1591,7 +1491,7 @@
1624                                  * ref for us as needed.
1625                                  */
1626                                 ieee80211_ref_node(ni);
1627 -                               IEEE80211_NODE_UNLOCK_IRQ_EARLY(nt);
1628 +                               IEEE80211_NODE_TABLE_UNLOCK_IRQ_EARLY(nt);
1629                                 ieee80211_send_nulldata(ni);
1630                                 /* XXX stat? */
1631                                 goto restart;
1632 @@ -1614,18 +1514,18 @@
1633                          */
1634                         ni->ni_vap->iv_stats.is_node_timeout++;
1635                         ieee80211_ref_node(ni);
1636 -                       IEEE80211_NODE_UNLOCK_IRQ_EARLY(nt);
1637 +                       IEEE80211_NODE_TABLE_UNLOCK_IRQ_EARLY(nt);
1638                         if (ni->ni_associd != 0) {
1639                                 IEEE80211_SEND_MGMT(ni,
1640                                         IEEE80211_FC0_SUBTYPE_DEAUTH,
1641                                         IEEE80211_REASON_AUTH_EXPIRE);
1642                         }
1643                         ieee80211_node_leave(ni);
1644 -                       ieee80211_free_node(ni);
1645 +                       ieee80211_unref_node(&ni);
1646                         goto restart;
1647                 }
1648         }
1649 -       IEEE80211_NODE_UNLOCK_IRQ(nt);
1650 +       IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
1651  
1652         IEEE80211_SCAN_UNLOCK_IRQ(nt);
1653  }
1654 @@ -1660,21 +1560,23 @@
1655  
1656         IEEE80211_SCAN_LOCK_IRQ(nt);
1657         gen = ++nt->nt_scangen;
1658 +       
1659  restart:
1660 -       IEEE80211_NODE_LOCK(nt);
1661 +       IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
1662         TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
1663                 if (dev != NULL && ni->ni_vap->iv_dev != dev) 
1664                         continue;  /* skip node not for this vap */
1665                 if (ni->ni_scangen != gen) {
1666                         ni->ni_scangen = gen;
1667                         (void) ieee80211_ref_node(ni);
1668 -                       IEEE80211_NODE_UNLOCK(nt);
1669 +                       IEEE80211_NODE_TABLE_UNLOCK_IRQ_EARLY(nt);
1670                         (*f)(arg, ni);
1671 -                       ieee80211_free_node(ni);
1672 +                       
1673 +                       ieee80211_unref_node(&ni);
1674                         goto restart;
1675                 }
1676         }
1677 -       IEEE80211_NODE_UNLOCK(nt);
1678 +       IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
1679  
1680         IEEE80211_SCAN_UNLOCK_IRQ(nt);
1681  }
1682 @@ -1948,9 +1850,20 @@
1683                 "station with aid %d leaves (refcnt %u)",
1684                 IEEE80211_NODE_AID(ni), ieee80211_node_refcnt(ni));
1685  
1686 +       /* From this point onwards we can no longer find the node,
1687 +        * so no more references are generated
1688 +        */
1689 +       ieee80211_remove_wds_addr(nt, ni->ni_macaddr);
1690 +       ieee80211_del_wds_node(nt, ni);
1691 +       IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
1692 +       _node_table_leave(nt, ni);
1693 +       IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
1694 +
1695         /*
1696          * If node wasn't previously associated all
1697          * we need to do is reclaim the reference.
1698 +        * This also goes for nodes that are auth'ed but
1699 +        * not associated.
1700          */
1701         /* XXX ibss mode bypasses 11g and notification */
1702         if (ni->ni_associd == 0)
1703 @@ -1968,9 +1881,11 @@
1704         IEEE80211_LOCK_IRQ(ic);
1705         if (vap->iv_aid_bitmap != NULL)
1706                 IEEE80211_AID_CLR(vap, ni->ni_associd);
1707 +
1708         ni->ni_associd = 0;
1709         vap->iv_sta_assoc--;
1710         ic->ic_sta_assoc--;
1711 +
1712  #ifdef ATH_SUPERG_XR
1713         if (ni->ni_vap->iv_flags & IEEE80211_F_XR)
1714                 ic->ic_xr_sta_assoc--;
1715 @@ -1981,6 +1896,7 @@
1716         if (IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
1717                 ieee80211_node_leave_11g(ni);
1718         IEEE80211_UNLOCK_IRQ(ic);
1719 +
1720         /*
1721          * Cleanup station state.  In particular clear various
1722          * state that might otherwise be reused if the node
1723 @@ -1990,19 +1906,10 @@
1724         ieee80211_sta_leave(ni);
1725  done:
1726         /*
1727 -        * Remove the node from any table it's recorded in and
1728 -        * drop the caller's reference.  Removal from the table
1729 -        * is important to ensure the node is not reprocessed
1730 -        * for inactivity.
1731 -        */
1732 -       if (nt != NULL) {
1733 -               IEEE80211_NODE_LOCK_IRQ(nt);
1734 -               node_reclaim(nt, ni);
1735 -               IEEE80211_NODE_UNLOCK_IRQ(nt);
1736 -               ieee80211_remove_wds_addr(nt,ni->ni_macaddr);
1737 -               ieee80211_del_wds_node(nt,ni);
1738 -       } else
1739 -               ieee80211_free_node(ni);
1740 +        * Run a cleanup and then drop the caller's reference
1741 +        */
1742 +       ic->ic_node_cleanup(ni);
1743 +       ieee80211_unref_node(&ni);
1744  }
1745  EXPORT_SYMBOL(ieee80211_node_leave);
1746  
1747 @@ -2062,25 +1969,8 @@
1748  void
1749  ieee80211_node_reset(struct ieee80211_node *ni, struct ieee80211vap *vap)
1750  {
1751 -       if (ni != NULL) {
1752 -               struct ieee80211_node_table *nt = ni->ni_table;
1753 -               if (!nt)
1754 -                       nt = &vap->iv_ic->ic_sta;
1755 -               IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_bss->ni_bssid);
1756 -               ni->ni_prev_vap = ni->ni_vap;
1757 -               ni->ni_vap = vap;
1758 -               ni->ni_ic = vap->iv_ic;
1759 -               /* 
1760 -                * if node not found in the node table
1761 -                * add it to the node table .
1762 -                */
1763 -               if(nt && ieee80211_find_node(nt, ni->ni_macaddr) != ni) {
1764 -                       int hash = IEEE80211_NODE_HASH(ni->ni_macaddr);
1765 -                       IEEE80211_NODE_LOCK_IRQ(nt);
1766 -                       TAILQ_INSERT_TAIL(&nt->nt_node, ni, ni_list);
1767 -                       LIST_INSERT_HEAD(&nt->nt_hash[hash], ni, ni_hash);
1768 -                       ni->ni_table = nt;
1769 -                       IEEE80211_NODE_UNLOCK_IRQ(nt);
1770 -               }
1771 -       }
1772 +       IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_bss->ni_bssid);
1773 +       ni->ni_prev_vap = ni->ni_vap;
1774 +       ni->ni_vap = vap;
1775 +       ni->ni_ic = vap->iv_ic;
1776  }
1777 diff -ur madwifi.old/net80211/ieee80211_node.h madwifi.dev/net80211/ieee80211_node.h
1778 --- madwifi.old/net80211/ieee80211_node.h       2007-03-06 11:59:28.000000000 +0100
1779 +++ madwifi.dev/net80211/ieee80211_node.h       2007-05-21 08:10:46.869753416 +0200
1780 @@ -52,14 +52,14 @@
1781   * authorized.  The latter timeout is shorter to more aggressively
1782   * reclaim nodes that leave part way through the 802.1x exchange.
1783   */
1784 -#define        IEEE80211_INACT_WAIT    15              /* inactivity interval (secs) */
1785 +#define        IEEE80211_INACT_WAIT    15                              /* inactivity interval (secs) */
1786  #define        IEEE80211_INACT_INIT    (30/IEEE80211_INACT_WAIT)       /* initial */
1787  #define        IEEE80211_INACT_AUTH    (180/IEEE80211_INACT_WAIT)      /* associated but not authorized */
1788  #define        IEEE80211_INACT_RUN     (300/IEEE80211_INACT_WAIT)      /* authorized */
1789  #define        IEEE80211_INACT_PROBE   (30/IEEE80211_INACT_WAIT)       /* probe */
1790  #define        IEEE80211_INACT_SCAN    (300/IEEE80211_INACT_WAIT)      /* scanned */
1791  
1792 -#define        IEEE80211_TRANS_WAIT    5               /* mgt frame tx timer (secs) */
1793 +#define        IEEE80211_TRANS_WAIT    5                               /* mgt frame tx timer (secs) */
1794  
1795  #define        IEEE80211_NODE_HASHSIZE 32
1796  /* simple hash is enough for variation of macaddr */
1797 @@ -94,7 +94,8 @@
1798         struct ieee80211_node_table *ni_table;
1799         TAILQ_ENTRY(ieee80211_node) ni_list;
1800         LIST_ENTRY(ieee80211_node) ni_hash;
1801 -       atomic_t ni_refcnt;
1802 +       // ieee80211_node_lock_t ni_nodelock;   /* on node - notably for ref counting */
1803 +       ieee80211_node_ref_count_t ni_refcnt;
1804         u_int ni_scangen;                       /* gen# for timeout scan */
1805         u_int8_t ni_authmode;                   /* authentication algorithm */
1806         u_int16_t ni_flags;                     /* special-purpose state */
1807 @@ -121,13 +122,13 @@
1808         u_int16_t ni_associd;                   /* assoc response */
1809         u_int16_t ni_txpower;                   /* current transmit power (in 0.5 dBm) */
1810         u_int16_t ni_vlan;                      /* vlan tag */
1811 -       u_int32_t *ni_challenge;                        /* shared-key challenge */
1812 +       u_int32_t *ni_challenge;                /* shared-key challenge */
1813         u_int8_t *ni_wpa_ie;                    /* captured WPA ie */
1814         u_int8_t *ni_rsn_ie;                    /* captured RSN ie */
1815         u_int8_t *ni_wme_ie;                    /* captured WME ie */
1816         u_int8_t *ni_ath_ie;                    /* captured Atheros ie */
1817 -       u_int16_t ni_txseqs[17];                        /* tx seq per-tid */
1818 -       u_int16_t ni_rxseqs[17];                        /* rx seq previous per-tid*/
1819 +       u_int16_t ni_txseqs[17];                /* tx seq per-tid */
1820 +       u_int16_t ni_rxseqs[17];                /* rx seq previous per-tid*/
1821         u_int32_t ni_rxfragstamp;               /* time stamp of last rx frag */
1822         struct sk_buff *ni_rxfrag;              /* rx frag reassembly */
1823         struct ieee80211_rsnparms ni_rsn;       /* RSN/WPA parameters */
1824 @@ -156,7 +157,7 @@
1825         struct ieee80211_channel *ni_chan;
1826         u_int16_t ni_fhdwell;                   /* FH only */
1827         u_int8_t ni_fhindex;                    /* FH only */
1828 -       u_int8_t ni_erp;                                /* ERP from beacon/probe resp */
1829 +       u_int8_t ni_erp;                        /* ERP from beacon/probe resp */
1830         u_int16_t ni_timoff;                    /* byte offset to TIM ie */
1831  
1832         /* others */
1833 @@ -168,7 +169,7 @@
1834         struct ieee80211vap *ni_prev_vap;       /* previously associated vap */
1835         u_int8_t ni_uapsd;                      /* U-APSD per-node flags matching WMM STA Qos Info field */
1836         u_int8_t ni_uapsd_maxsp;                /* maxsp from flags above */
1837 -       u_int16_t ni_uapsd_trigseq[WME_NUM_AC];         /* trigger suppression on retry */
1838 +       u_int16_t ni_uapsd_trigseq[WME_NUM_AC]; /* trigger suppression on retry */
1839         __le16 ni_pschangeseq;
1840  };
1841  MALLOC_DECLARE(M_80211_NODE);
1842 @@ -186,20 +187,6 @@
1843  #define WME_UAPSD_NODE_INVALIDSEQ      0xffff
1844  #define WME_UAPSD_NODE_TRIGSEQINIT(_ni)        (memset(&(_ni)->ni_uapsd_trigseq[0], 0xff, sizeof((_ni)->ni_uapsd_trigseq)))
1845  
1846 -static __inline struct ieee80211_node *
1847 -ieee80211_ref_node(struct ieee80211_node *ni)
1848 -{
1849 -       ieee80211_node_incref(ni);
1850 -       return ni;
1851 -}
1852 -
1853 -static __inline void
1854 -ieee80211_unref_node(struct ieee80211_node **ni)
1855 -{
1856 -       ieee80211_node_decref(*ni);
1857 -       *ni = NULL;                     /* guard against use */
1858 -}
1859 -
1860  void ieee80211_node_attach(struct ieee80211com *);
1861  void ieee80211_node_detach(struct ieee80211com *);
1862  void ieee80211_node_vattach(struct ieee80211vap *);
1863 @@ -242,43 +229,39 @@
1864   * is a second table for associated stations or neighbors.
1865   */
1866  struct ieee80211_node_table {
1867 +       const char *nt_name;                    /* for debugging */
1868         struct ieee80211com *nt_ic;             /* back reference */
1869 -       ieee80211_node_lock_t nt_nodelock;      /* on node table */
1870 +       ieee80211_node_table_lock_t nt_nodelock;        /* on node table */
1871         TAILQ_HEAD(, ieee80211_node) nt_node;   /* information of all nodes */
1872         ATH_LIST_HEAD(, ieee80211_node) nt_hash[IEEE80211_NODE_HASHSIZE];
1873         ATH_LIST_HEAD(, ieee80211_wds_addr) nt_wds_hash[IEEE80211_NODE_HASHSIZE];
1874 -       const char *nt_name;                    /* for debugging */
1875         ieee80211_scan_lock_t nt_scanlock;      /* on nt_scangen */
1876         u_int nt_scangen;                       /* gen# for timeout scan */
1877         int nt_inact_init;                      /* initial node inact setting */
1878         struct timer_list nt_wds_aging_timer;   /* timer to age out wds entries */
1879  };
1880  
1881 -struct ieee80211_node *ieee80211_alloc_node(struct ieee80211_node_table *,
1882 -       struct ieee80211vap *, const u_int8_t *);
1883 -struct ieee80211_node *ieee80211_tmp_node(struct ieee80211vap *,
1884 -       const u_int8_t *);
1885 -struct ieee80211_node *ieee80211_dup_bss(struct ieee80211vap *,
1886 +struct ieee80211_node *ieee80211_alloc_node_table(struct ieee80211vap *,
1887         const u_int8_t *);
1888 +struct ieee80211_node *ieee80211_dup_bss(struct ieee80211vap *, 
1889 +       const u_int8_t *, unsigned char);
1890  void ieee80211_node_reset(struct ieee80211_node *, struct ieee80211vap *);
1891  #ifdef IEEE80211_DEBUG_REFCNT
1892 -void ieee80211_free_node_debug(struct ieee80211_node *, const char *, int);
1893  struct ieee80211_node *ieee80211_find_node_debug(struct ieee80211_node_table *,
1894         const u_int8_t *, const char *, int);
1895  struct ieee80211_node *ieee80211_find_rxnode_debug(struct ieee80211com *,
1896         const struct ieee80211_frame_min *, const char *, int);
1897  struct ieee80211_node *ieee80211_find_txnode_debug(struct ieee80211vap *,
1898         const u_int8_t *, const char *, int);
1899 -#define        ieee80211_free_node(ni) \
1900 -       ieee80211_free_node_debug(ni, __func__, __LINE__)
1901 -#define        ieee80211_find_node(nt, mac) \
1902 -       ieee80211_find_node_debug(nt, mac, __func__, __LINE__)
1903 -#define        ieee80211_find_rxnode(nt, wh) \
1904 -       ieee80211_find_rxnode_debug(nt, wh, __func__, __LINE__)
1905 -#define        ieee80211_find_txnode(nt, mac) \
1906 -       ieee80211_find_txnode_debug(nt, mac, __func__, __LINE__)
1907 +#define        ieee80211_unref_node(_ni) \
1908 +       ieee80211_unref_node_debug(_ni, __func__, __LINE__)
1909 +#define        ieee80211_find_node(_nt, _mac) \
1910 +       ieee80211_find_node_debug(_nt, _mac, __func__, __LINE__)
1911 +#define        ieee80211_find_rxnode(_nt, _wh) \
1912 +       ieee80211_find_rxnode_debug(_nt, _wh, __func__, __LINE__)
1913 +#define        ieee80211_find_txnode(_nt, _mac) \
1914 +       ieee80211_find_txnode_debug(_nt, _mac, __func__, __LINE__)
1915  #else
1916 -void ieee80211_free_node(struct ieee80211_node *);
1917  
1918  struct ieee80211_node *ieee80211_find_node(struct ieee80211_node_table *,
1919         const u_int8_t *);
1920 @@ -287,6 +270,53 @@
1921  struct ieee80211_node *ieee80211_find_txnode(struct ieee80211vap *,
1922         const u_int8_t *);
1923  #endif
1924 +
1925 +void _ieee80211_free_node(struct ieee80211_node *);
1926 +
1927 +static __inline struct ieee80211_node *
1928 +ieee80211_ref_node(struct ieee80211_node *ni)
1929 +{
1930 +       ieee80211_node_incref(ni);
1931 +       return ni;
1932 +}
1933 +
1934 +static __inline struct ieee80211_node *
1935 +_ieee80211_pass_node(struct ieee80211_node **pni) {
1936 +       struct ieee80211_node *tmp = *pni;
1937 +       *pni = NULL;
1938 +       return (tmp);
1939 +}
1940 +
1941 +#define PASS_NODE(_ni) \
1942 +       _ieee80211_pass_node(&_ni)
1943 +
1944 +static __inline int
1945 +_ieee80211_unref_node(struct ieee80211_node *ni) {
1946 +       if (ieee80211_node_dectestref(ni)) {
1947 +               _ieee80211_free_node(ni);
1948 +               return 1;
1949 +       } else {
1950 +               return 0;
1951 +       }
1952 +}
1953 +
1954 +static __inline void
1955 +#ifdef IEEE80211_DEBUG_REFCNT
1956 +ieee80211_unref_node_debug(struct ieee80211_node **pni, const char *func, int line)
1957 +#else
1958 +ieee80211_unref_node(struct ieee80211_node **pni)
1959 +#endif
1960 +{      
1961 +       struct ieee80211_node *ni = *pni;
1962 +#ifdef IEEE80211_DEBUG_REFCNT
1963 +       IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_NODE,
1964 +               "%s (%s:%u) %p<%s> refcnt %d\n", __func__, func, line, ni,
1965 +                ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni) - 1);
1966 +#endif
1967 +       _ieee80211_unref_node(ni); 
1968 +       *pni = NULL;                    /* guard against use */
1969 +}
1970 +
1971  int ieee80211_add_wds_addr(struct ieee80211_node_table *, struct ieee80211_node *,
1972         const u_int8_t *, u_int8_t);
1973  void ieee80211_remove_wds_addr(struct ieee80211_node_table *, const u_int8_t *);
1974 diff -ur madwifi.old/net80211/ieee80211_output.c madwifi.dev/net80211/ieee80211_output.c
1975 --- madwifi.old/net80211/ieee80211_output.c     2007-05-18 13:19:16.000000000 +0200
1976 +++ madwifi.dev/net80211/ieee80211_output.c     2007-05-21 08:10:46.870753264 +0200
1977 @@ -254,7 +254,7 @@
1978                 goto bad;
1979         }
1980         
1981 -       cb->ni = ni;
1982 +       cb->ni = ieee80211_ref_node(ni);
1983         
1984         /* power-save checks */
1985         if (WME_UAPSD_AC_CAN_TRIGGER(skb->priority, ni)) {
1986 @@ -293,13 +293,14 @@
1987         }
1988  #endif
1989         ieee80211_parent_queue_xmit(skb);
1990 +       ieee80211_unref_node(&ni);
1991         return 0;
1992  
1993  bad:
1994         if (skb != NULL)
1995                 dev_kfree_skb(skb);
1996         if (ni != NULL)
1997 -               ieee80211_free_node(ni);
1998 +               ieee80211_unref_node(&ni);
1999         return 0;
2000  }
2001  
2002 @@ -453,7 +454,7 @@
2003         if (skb == NULL) {
2004                 /* XXX debug msg */
2005                 vap->iv_stats.is_tx_nobuf++;
2006 -               ieee80211_free_node(ni);
2007 +               ieee80211_unref_node(&ni);
2008                 return -ENOMEM;
2009         }
2010         cb = (struct ieee80211_cb *)skb->cb;
2011 @@ -507,16 +508,14 @@
2012         u_int8_t *frm;
2013         int tid;
2014  
2015 -       ieee80211_ref_node(ni);
2016         skb = ieee80211_getmgtframe(&frm, 2);
2017         if (skb == NULL) {
2018                 /* XXX debug msg */
2019                 vap->iv_stats.is_tx_nobuf++;
2020 -               ieee80211_free_node(ni);
2021                 return -ENOMEM;
2022         }
2023         cb = (struct ieee80211_cb *)skb->cb;
2024 -       cb->ni = ni;
2025 +       cb->ni = ieee80211_ref_node(ni);
2026  
2027         skb->priority = ac;
2028         qwh = (struct ieee80211_qosframe *)skb_push(skb, sizeof(struct ieee80211_qosframe));
2029 @@ -865,7 +864,7 @@
2030                                 nt = &ic->ic_sta;
2031                                 ni_wds = ieee80211_find_wds_node(nt, eh.ether_shost);
2032                                 if (ni_wds)
2033 -                                       ieee80211_free_node(ni_wds); /* Decr ref count */
2034 +                                       ieee80211_unref_node(&ni_wds); /* Decr ref count */
2035                                 else
2036                                         ieee80211_add_wds_addr(nt, ni, eh.ether_shost, 0);
2037                         }
2038 @@ -1719,7 +1718,6 @@
2039                 __func__, __LINE__,
2040                 ni, ether_sprintf(ni->ni_macaddr),
2041                 ieee80211_node_refcnt(ni) + 1);
2042 -       ieee80211_ref_node(ni);
2043  
2044         /*
2045          * prreq frame format
2046 @@ -1735,7 +1733,6 @@
2047                vap->app_ie[IEEE80211_APPIE_FRAME_PROBE_REQ].length);
2048         if (skb == NULL) {
2049                 vap->iv_stats.is_tx_nobuf++;
2050 -               ieee80211_free_node(ni);
2051                 return -ENOMEM;
2052         }
2053  
2054 @@ -1758,7 +1755,7 @@
2055         skb_trim(skb, frm - skb->data);
2056  
2057         cb = (struct ieee80211_cb *)skb->cb;
2058 -       cb->ni = ni;
2059 +       cb->ni = ieee80211_ref_node(ni);
2060  
2061         wh = (struct ieee80211_frame *)
2062                 skb_push(skb, sizeof(struct ieee80211_frame));
2063 @@ -2234,7 +2231,7 @@
2064                 mod_timer(&vap->iv_mgtsend, jiffies + timer * HZ);
2065         return 0;
2066  bad:
2067 -       ieee80211_free_node(ni);
2068 +       ieee80211_unref_node(&ni);
2069         return ret;
2070  #undef senderr
2071  }
2072 diff -ur madwifi.old/net80211/ieee80211_power.c madwifi.dev/net80211/ieee80211_power.c
2073 --- madwifi.old/net80211/ieee80211_power.c      2007-05-18 13:19:16.000000000 +0200
2074 +++ madwifi.dev/net80211/ieee80211_power.c      2007-05-21 08:10:46.870753264 +0200
2075 @@ -109,13 +109,15 @@
2076  int
2077  ieee80211_node_saveq_drain(struct ieee80211_node *ni)
2078  {
2079 +       struct ieee80211_cb *cb = NULL;
2080         struct sk_buff *skb;
2081         int qlen;
2082  
2083         IEEE80211_NODE_SAVEQ_LOCK(ni);
2084         qlen = skb_queue_len(&ni->ni_savedq);
2085         while ((skb = __skb_dequeue(&ni->ni_savedq)) != NULL) {
2086 -               ieee80211_free_node(ni);
2087 +               cb = (struct ieee80211_cb *) skb->cb;
2088 +               ieee80211_unref_node(&cb->ni);
2089                 dev_kfree_skb_any(skb);
2090         }
2091         IEEE80211_NODE_SAVEQ_UNLOCK(ni);
2092 diff -ur madwifi.old/net80211/ieee80211_proto.c madwifi.dev/net80211/ieee80211_proto.c
2093 --- madwifi.old/net80211/ieee80211_proto.c      2006-12-08 18:20:08.000000000 +0100
2094 +++ madwifi.dev/net80211/ieee80211_proto.c      2007-05-21 08:10:46.871753112 +0200
2095 @@ -1456,7 +1456,7 @@
2096                                  */                             
2097                                 if (vap->iv_opmode == IEEE80211_M_WDS) {
2098                                         struct ieee80211_node *wds_ni;
2099 -                                       wds_ni = ieee80211_alloc_node(&ic->ic_sta, vap, vap->wds_mac);
2100 +                                       wds_ni = ieee80211_alloc_node_table(vap, vap->wds_mac);
2101                                         if (wds_ni != NULL) {
2102                                                 if (ieee80211_add_wds_addr(&ic->ic_sta, wds_ni, vap->wds_mac, 1) == 0) {
2103                                                         ieee80211_node_authorize(wds_ni);
2104 diff -ur madwifi.old/net80211/ieee80211_var.h madwifi.dev/net80211/ieee80211_var.h
2105 --- madwifi.old/net80211/ieee80211_var.h        2007-05-18 13:19:16.000000000 +0200
2106 +++ madwifi.dev/net80211/ieee80211_var.h        2007-05-21 08:12:01.499407984 +0200
2107 @@ -44,6 +44,8 @@
2108  
2109  #include <sys/queue.h>
2110  
2111 +struct ieee80211vap;
2112 +
2113  #include <net80211/_ieee80211.h>
2114  #include <net80211/ieee80211.h>
2115  #include <net80211/ieee80211_crypto.h>
2116 @@ -115,7 +117,6 @@
2117   * the underlying device and the net80211 layer is exposed here;
2118   * e.g. device-specific callbacks.
2119   */
2120 -struct ieee80211vap;
2121  
2122  struct ieee80211com {
2123         struct net_device *ic_dev;              /* associated device */
2124 @@ -236,8 +237,7 @@
2125         /* new station association callback/notification */
2126         void (*ic_newassoc)(struct ieee80211_node *, int);
2127         /* node state management */
2128 -       struct ieee80211_node *(*ic_node_alloc)(struct ieee80211_node_table *,
2129 -               struct ieee80211vap *);
2130 +       struct ieee80211_node *(*ic_node_alloc)(struct ieee80211vap *);
2131         void (*ic_node_free)(struct ieee80211_node *);
2132         void (*ic_node_cleanup)(struct ieee80211_node *);
2133         u_int8_t (*ic_node_getrssi)(const struct ieee80211_node *);
2134 diff -ur madwifi.old/net80211/ieee80211_wireless.c madwifi.dev/net80211/ieee80211_wireless.c
2135 --- madwifi.old/net80211/ieee80211_wireless.c   2007-05-18 13:19:16.000000000 +0200
2136 +++ madwifi.dev/net80211/ieee80211_wireless.c   2007-05-21 08:10:46.874752656 +0200
2137 @@ -3186,7 +3186,7 @@
2138                 error = -ENXIO;
2139         ieee80211_key_update_end(vap);
2140         if (ni != NULL)
2141 -               ieee80211_free_node(ni);
2142 +               ieee80211_unref_node(&ni);
2143  #ifdef ATH_SUPERG_XR
2144         /* set the same params on the xr vap device if exists */
2145         if (vap->iv_xrvap && !(vap->iv_flags & IEEE80211_F_XR))
2146 @@ -3246,7 +3246,7 @@
2147                 memset(ik.ik_keydata, 0, sizeof(ik.ik_keydata));
2148         }
2149         if (ni != NULL)
2150 -               ieee80211_free_node(ni);
2151 +               ieee80211_unref_node(&ni);
2152         return (copy_to_user(iwr->u.data.pointer, &ik, sizeof(ik)) ? -EFAULT : 0);
2153  }
2154  
2155 @@ -3271,7 +3271,7 @@
2156                         return -ENOENT; /* No such entity is a more appropriate error */
2157                 /* XXX error return */
2158                 ieee80211_crypto_delkey(vap, &ni->ni_ucastkey, ni);
2159 -               ieee80211_free_node(ni);
2160 +               ieee80211_unref_node(&ni);
2161         } else {
2162                 if (kix >= IEEE80211_WEP_NKID)
2163                         return -EINVAL;
2164 @@ -3382,7 +3382,7 @@
2165                                         return -EINVAL;
2166                                 if (dev == ni->ni_vap->iv_dev)
2167                                         domlme(mlme, ni);
2168 -                               ieee80211_free_node(ni);
2169 +                               ieee80211_unref_node(&ni);
2170                         } else
2171                                 ieee80211_iterate_dev_nodes(dev, &ic->ic_sta, domlme, mlme);
2172                         break;
2173 @@ -3401,7 +3401,7 @@
2174                         ieee80211_node_authorize(ni);
2175                 else
2176                         ieee80211_node_unauthorize(ni);
2177 -               ieee80211_free_node(ni);
2178 +               ieee80211_unref_node(&ni);
2179                 break;
2180         case IEEE80211_MLME_CLEAR_STATS:
2181                 if (vap->iv_opmode != IEEE80211_M_HOSTAP)
2182 @@ -3412,7 +3412,7 @@
2183                 
2184                 /* clear statistics */
2185                 memset(&ni->ni_stats, 0, sizeof(struct ieee80211_nodestats));
2186 -               ieee80211_free_node(ni);
2187 +               ieee80211_unref_node(&ni);
2188                 break;
2189         default:
2190                 return -EINVAL;
2191 @@ -3785,7 +3785,7 @@
2192                         ielen = sizeof(wpaie.rsn_ie);
2193                 memcpy(wpaie.rsn_ie, ni->ni_rsn_ie, ielen);
2194         }
2195 -       ieee80211_free_node(ni);
2196 +       ieee80211_unref_node(&ni);
2197         return (copy_to_user(iwr->u.data.pointer, &wpaie, sizeof(wpaie)) ?
2198                 -EFAULT : 0);
2199  }
2200 @@ -3813,7 +3813,7 @@
2201         /* NB: copy out only the statistics */
2202         error = copy_to_user(iwr->u.data.pointer + off, &ni->ni_stats,
2203                 iwr->u.data.length - off);
2204 -       ieee80211_free_node(ni);
2205 +       ieee80211_unref_node(&ni);
2206         return (error ? -EFAULT : 0);
2207  }
2208