diff options
Diffstat (limited to 'net/ieee80211/softmac/ieee80211softmac_assoc.c')
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_assoc.c | 72 |
1 files changed, 38 insertions, 34 deletions
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c index d4c79ce16871..5d90b9a6ee50 100644 --- a/net/ieee80211/softmac/ieee80211softmac_assoc.c +++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c | |||
@@ -82,51 +82,52 @@ ieee80211softmac_assoc_timeout(void *d) | |||
82 | ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, NULL); | 82 | ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, NULL); |
83 | } | 83 | } |
84 | 84 | ||
85 | /* Sends out a disassociation request to the desired AP */ | ||
86 | void | 85 | void |
87 | ieee80211softmac_disassoc(struct ieee80211softmac_device *mac, u16 reason) | 86 | ieee80211softmac_disassoc(struct ieee80211softmac_device *mac) |
88 | { | 87 | { |
89 | unsigned long flags; | 88 | unsigned long flags; |
89 | |||
90 | spin_lock_irqsave(&mac->lock, flags); | ||
91 | if (mac->associnfo.associating) | ||
92 | cancel_delayed_work(&mac->associnfo.timeout); | ||
93 | |||
94 | netif_carrier_off(mac->dev); | ||
95 | |||
96 | mac->associated = 0; | ||
97 | mac->associnfo.bssvalid = 0; | ||
98 | mac->associnfo.associating = 0; | ||
99 | ieee80211softmac_init_txrates(mac); | ||
100 | ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL); | ||
101 | spin_unlock_irqrestore(&mac->lock, flags); | ||
102 | } | ||
103 | |||
104 | /* Sends out a disassociation request to the desired AP */ | ||
105 | void | ||
106 | ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reason) | ||
107 | { | ||
90 | struct ieee80211softmac_network *found; | 108 | struct ieee80211softmac_network *found; |
91 | 109 | ||
92 | if (mac->associnfo.bssvalid && mac->associated) { | 110 | if (mac->associnfo.bssvalid && mac->associated) { |
93 | found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); | 111 | found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); |
94 | if (found) | 112 | if (found) |
95 | ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason); | 113 | ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason); |
96 | } else if (mac->associnfo.associating) { | ||
97 | cancel_delayed_work(&mac->associnfo.timeout); | ||
98 | } | 114 | } |
99 | 115 | ||
100 | /* Change our state */ | 116 | ieee80211softmac_disassoc(mac); |
101 | spin_lock_irqsave(&mac->lock, flags); | ||
102 | /* Do NOT clear bssvalid as that will break ieee80211softmac_assoc_work! */ | ||
103 | mac->associated = 0; | ||
104 | mac->associnfo.associating = 0; | ||
105 | ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL); | ||
106 | spin_unlock_irqrestore(&mac->lock, flags); | ||
107 | } | 117 | } |
108 | 118 | ||
109 | static inline int | 119 | static inline int |
110 | we_support_all_basic_rates(struct ieee80211softmac_device *mac, u8 *from, u8 from_len) | 120 | we_support_all_basic_rates(struct ieee80211softmac_device *mac, u8 *from, u8 from_len) |
111 | { | 121 | { |
112 | int idx, search, found; | 122 | int idx; |
113 | u8 rate, search_rate; | 123 | u8 rate; |
114 | 124 | ||
115 | for (idx = 0; idx < (from_len); idx++) { | 125 | for (idx = 0; idx < (from_len); idx++) { |
116 | rate = (from)[idx]; | 126 | rate = (from)[idx]; |
117 | if (!(rate & IEEE80211_BASIC_RATE_MASK)) | 127 | if (!(rate & IEEE80211_BASIC_RATE_MASK)) |
118 | continue; | 128 | continue; |
119 | found = 0; | ||
120 | rate &= ~IEEE80211_BASIC_RATE_MASK; | 129 | rate &= ~IEEE80211_BASIC_RATE_MASK; |
121 | for (search = 0; search < mac->ratesinfo.count; search++) { | 130 | if (!ieee80211softmac_ratesinfo_rate_supported(&mac->ratesinfo, rate)) |
122 | search_rate = mac->ratesinfo.rates[search]; | ||
123 | search_rate &= ~IEEE80211_BASIC_RATE_MASK; | ||
124 | if (rate == search_rate) { | ||
125 | found = 1; | ||
126 | break; | ||
127 | } | ||
128 | } | ||
129 | if (!found) | ||
130 | return 0; | 131 | return 0; |
131 | } | 132 | } |
132 | return 1; | 133 | return 1; |
@@ -176,14 +177,18 @@ ieee80211softmac_assoc_work(void *d) | |||
176 | struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d; | 177 | struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d; |
177 | struct ieee80211softmac_network *found = NULL; | 178 | struct ieee80211softmac_network *found = NULL; |
178 | struct ieee80211_network *net = NULL, *best = NULL; | 179 | struct ieee80211_network *net = NULL, *best = NULL; |
180 | int bssvalid; | ||
179 | unsigned long flags; | 181 | unsigned long flags; |
180 | 182 | ||
183 | /* ieee80211_disassoc might clear this */ | ||
184 | bssvalid = mac->associnfo.bssvalid; | ||
185 | |||
181 | /* meh */ | 186 | /* meh */ |
182 | if (mac->associated) | 187 | if (mac->associated) |
183 | ieee80211softmac_disassoc(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT); | 188 | ieee80211softmac_send_disassoc_req(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT); |
184 | 189 | ||
185 | /* try to find the requested network in our list, if we found one already */ | 190 | /* try to find the requested network in our list, if we found one already */ |
186 | if (mac->associnfo.bssvalid || mac->associnfo.bssfixed) | 191 | if (bssvalid || mac->associnfo.bssfixed) |
187 | found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); | 192 | found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); |
188 | 193 | ||
189 | /* Search the ieee80211 networks for this network if we didn't find it by bssid, | 194 | /* Search the ieee80211 networks for this network if we didn't find it by bssid, |
@@ -297,6 +302,9 @@ ieee80211softmac_associated(struct ieee80211softmac_device *mac, | |||
297 | struct ieee80211softmac_network *net) | 302 | struct ieee80211softmac_network *net) |
298 | { | 303 | { |
299 | mac->associnfo.associating = 0; | 304 | mac->associnfo.associating = 0; |
305 | mac->associnfo.supported_rates = net->supported_rates; | ||
306 | ieee80211softmac_recalc_txrates(mac); | ||
307 | |||
300 | mac->associated = 1; | 308 | mac->associated = 1; |
301 | if (mac->set_bssid_filter) | 309 | if (mac->set_bssid_filter) |
302 | mac->set_bssid_filter(mac->dev, net->bssid); | 310 | mac->set_bssid_filter(mac->dev, net->bssid); |
@@ -380,7 +388,6 @@ ieee80211softmac_handle_disassoc(struct net_device * dev, | |||
380 | struct ieee80211_disassoc *disassoc) | 388 | struct ieee80211_disassoc *disassoc) |
381 | { | 389 | { |
382 | struct ieee80211softmac_device *mac = ieee80211_priv(dev); | 390 | struct ieee80211softmac_device *mac = ieee80211_priv(dev); |
383 | unsigned long flags; | ||
384 | 391 | ||
385 | if (unlikely(!mac->running)) | 392 | if (unlikely(!mac->running)) |
386 | return -ENODEV; | 393 | return -ENODEV; |
@@ -392,14 +399,11 @@ ieee80211softmac_handle_disassoc(struct net_device * dev, | |||
392 | return 0; | 399 | return 0; |
393 | 400 | ||
394 | dprintk(KERN_INFO PFX "got disassoc frame\n"); | 401 | dprintk(KERN_INFO PFX "got disassoc frame\n"); |
395 | netif_carrier_off(dev); | 402 | ieee80211softmac_disassoc(mac); |
396 | spin_lock_irqsave(&mac->lock, flags); | 403 | |
397 | mac->associnfo.bssvalid = 0; | 404 | /* try to reassociate */ |
398 | mac->associated = 0; | ||
399 | ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL); | ||
400 | schedule_work(&mac->associnfo.work); | 405 | schedule_work(&mac->associnfo.work); |
401 | spin_unlock_irqrestore(&mac->lock, flags); | 406 | |
402 | |||
403 | return 0; | 407 | return 0; |
404 | } | 408 | } |
405 | 409 | ||