|
@@ -82,51 +82,52 @@ ieee80211softmac_assoc_timeout(void *d)
|
|
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, NULL);
|
|
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, NULL);
|
|
}
|
|
}
|
|
|
|
|
|
-/* Sends out a disassociation request to the desired AP */
|
|
|
|
void
|
|
void
|
|
-ieee80211softmac_disassoc(struct ieee80211softmac_device *mac, u16 reason)
|
|
|
|
|
|
+ieee80211softmac_disassoc(struct ieee80211softmac_device *mac)
|
|
{
|
|
{
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
|
|
+
|
|
|
|
+ spin_lock_irqsave(&mac->lock, flags);
|
|
|
|
+ if (mac->associnfo.associating)
|
|
|
|
+ cancel_delayed_work(&mac->associnfo.timeout);
|
|
|
|
+
|
|
|
|
+ netif_carrier_off(mac->dev);
|
|
|
|
+
|
|
|
|
+ mac->associated = 0;
|
|
|
|
+ mac->associnfo.bssvalid = 0;
|
|
|
|
+ mac->associnfo.associating = 0;
|
|
|
|
+ ieee80211softmac_init_txrates(mac);
|
|
|
|
+ ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
|
|
|
|
+ spin_unlock_irqrestore(&mac->lock, flags);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Sends out a disassociation request to the desired AP */
|
|
|
|
+void
|
|
|
|
+ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reason)
|
|
|
|
+{
|
|
struct ieee80211softmac_network *found;
|
|
struct ieee80211softmac_network *found;
|
|
|
|
|
|
if (mac->associnfo.bssvalid && mac->associated) {
|
|
if (mac->associnfo.bssvalid && mac->associated) {
|
|
found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
|
|
found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
|
|
if (found)
|
|
if (found)
|
|
ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason);
|
|
ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason);
|
|
- } else if (mac->associnfo.associating) {
|
|
|
|
- cancel_delayed_work(&mac->associnfo.timeout);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- /* Change our state */
|
|
|
|
- spin_lock_irqsave(&mac->lock, flags);
|
|
|
|
- /* Do NOT clear bssvalid as that will break ieee80211softmac_assoc_work! */
|
|
|
|
- mac->associated = 0;
|
|
|
|
- mac->associnfo.associating = 0;
|
|
|
|
- ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
|
|
|
|
- spin_unlock_irqrestore(&mac->lock, flags);
|
|
|
|
|
|
+ ieee80211softmac_disassoc(mac);
|
|
}
|
|
}
|
|
|
|
|
|
static inline int
|
|
static inline int
|
|
we_support_all_basic_rates(struct ieee80211softmac_device *mac, u8 *from, u8 from_len)
|
|
we_support_all_basic_rates(struct ieee80211softmac_device *mac, u8 *from, u8 from_len)
|
|
{
|
|
{
|
|
- int idx, search, found;
|
|
|
|
- u8 rate, search_rate;
|
|
|
|
|
|
+ int idx;
|
|
|
|
+ u8 rate;
|
|
|
|
|
|
for (idx = 0; idx < (from_len); idx++) {
|
|
for (idx = 0; idx < (from_len); idx++) {
|
|
rate = (from)[idx];
|
|
rate = (from)[idx];
|
|
if (!(rate & IEEE80211_BASIC_RATE_MASK))
|
|
if (!(rate & IEEE80211_BASIC_RATE_MASK))
|
|
continue;
|
|
continue;
|
|
- found = 0;
|
|
|
|
rate &= ~IEEE80211_BASIC_RATE_MASK;
|
|
rate &= ~IEEE80211_BASIC_RATE_MASK;
|
|
- for (search = 0; search < mac->ratesinfo.count; search++) {
|
|
|
|
- search_rate = mac->ratesinfo.rates[search];
|
|
|
|
- search_rate &= ~IEEE80211_BASIC_RATE_MASK;
|
|
|
|
- if (rate == search_rate) {
|
|
|
|
- found = 1;
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if (!found)
|
|
|
|
|
|
+ if (!ieee80211softmac_ratesinfo_rate_supported(&mac->ratesinfo, rate))
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
return 1;
|
|
@@ -176,14 +177,18 @@ ieee80211softmac_assoc_work(void *d)
|
|
struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d;
|
|
struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d;
|
|
struct ieee80211softmac_network *found = NULL;
|
|
struct ieee80211softmac_network *found = NULL;
|
|
struct ieee80211_network *net = NULL, *best = NULL;
|
|
struct ieee80211_network *net = NULL, *best = NULL;
|
|
|
|
+ int bssvalid;
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ /* ieee80211_disassoc might clear this */
|
|
|
|
+ bssvalid = mac->associnfo.bssvalid;
|
|
|
|
+
|
|
/* meh */
|
|
/* meh */
|
|
if (mac->associated)
|
|
if (mac->associated)
|
|
- ieee80211softmac_disassoc(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
|
|
|
|
|
|
+ ieee80211softmac_send_disassoc_req(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
|
|
|
|
|
|
/* try to find the requested network in our list, if we found one already */
|
|
/* try to find the requested network in our list, if we found one already */
|
|
- if (mac->associnfo.bssvalid || mac->associnfo.bssfixed)
|
|
|
|
|
|
+ if (bssvalid || mac->associnfo.bssfixed)
|
|
found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
|
|
found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
|
|
|
|
|
|
/* Search the ieee80211 networks for this network if we didn't find it by bssid,
|
|
/* 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,
|
|
struct ieee80211softmac_network *net)
|
|
struct ieee80211softmac_network *net)
|
|
{
|
|
{
|
|
mac->associnfo.associating = 0;
|
|
mac->associnfo.associating = 0;
|
|
|
|
+ mac->associnfo.supported_rates = net->supported_rates;
|
|
|
|
+ ieee80211softmac_recalc_txrates(mac);
|
|
|
|
+
|
|
mac->associated = 1;
|
|
mac->associated = 1;
|
|
if (mac->set_bssid_filter)
|
|
if (mac->set_bssid_filter)
|
|
mac->set_bssid_filter(mac->dev, net->bssid);
|
|
mac->set_bssid_filter(mac->dev, net->bssid);
|
|
@@ -380,7 +388,6 @@ ieee80211softmac_handle_disassoc(struct net_device * dev,
|
|
struct ieee80211_disassoc *disassoc)
|
|
struct ieee80211_disassoc *disassoc)
|
|
{
|
|
{
|
|
struct ieee80211softmac_device *mac = ieee80211_priv(dev);
|
|
struct ieee80211softmac_device *mac = ieee80211_priv(dev);
|
|
- unsigned long flags;
|
|
|
|
|
|
|
|
if (unlikely(!mac->running))
|
|
if (unlikely(!mac->running))
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
@@ -392,14 +399,11 @@ ieee80211softmac_handle_disassoc(struct net_device * dev,
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
dprintk(KERN_INFO PFX "got disassoc frame\n");
|
|
dprintk(KERN_INFO PFX "got disassoc frame\n");
|
|
- netif_carrier_off(dev);
|
|
|
|
- spin_lock_irqsave(&mac->lock, flags);
|
|
|
|
- mac->associnfo.bssvalid = 0;
|
|
|
|
- mac->associated = 0;
|
|
|
|
- ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
|
|
|
|
|
|
+ ieee80211softmac_disassoc(mac);
|
|
|
|
+
|
|
|
|
+ /* try to reassociate */
|
|
schedule_work(&mac->associnfo.work);
|
|
schedule_work(&mac->associnfo.work);
|
|
- spin_unlock_irqrestore(&mac->lock, flags);
|
|
|
|
-
|
|
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|