diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/ieee80211_i.h | 1 | ||||
-rw-r--r-- | net/mac80211/iface.c | 16 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 38 | ||||
-rw-r--r-- | net/mac80211/scan.c | 12 | ||||
-rw-r--r-- | net/mac80211/wme.c | 9 |
5 files changed, 53 insertions, 23 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ecbc8e0cb3e7..fbb91f1aebb2 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -972,6 +972,7 @@ int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len); void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); +void ieee80211_scan_failed(struct ieee80211_local *local); int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, struct cfg80211_scan_request *req); struct ieee80211_bss * diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 2acc416e77e1..f9f27b9cadbe 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -370,6 +370,18 @@ static int ieee80211_stop(struct net_device *dev) rcu_read_unlock(); /* + * Announce that we are leaving the network, in case we are a + * station interface type. This must be done before removing + * all stations associated with sta_info_flush, otherwise STA + * information will be gone and no announce being done. + */ + if (sdata->vif.type == NL80211_IFTYPE_STATION) { + if (sdata->u.mgd.state != IEEE80211_STA_MLME_DISABLED) + ieee80211_sta_deauthenticate(sdata, + WLAN_REASON_DEAUTH_LEAVING); + } + + /* * Remove all stations associated with this interface. * * This must be done before calling ops->remove_interface() @@ -454,10 +466,6 @@ static int ieee80211_stop(struct net_device *dev) netif_addr_unlock_bh(local->mdev); break; case NL80211_IFTYPE_STATION: - /* Announce that we are leaving the network. */ - if (sdata->u.mgd.state != IEEE80211_STA_MLME_DISABLED) - ieee80211_sta_deauthenticate(sdata, - WLAN_REASON_DEAUTH_LEAVING); memset(sdata->u.mgd.bssid, 0, ETH_ALEN); del_timer_sync(&sdata->u.mgd.chswitch_timer); del_timer_sync(&sdata->u.mgd.timer); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 391445c6b892..841b8450b3de 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -417,9 +417,6 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, memset(¶ms, 0, sizeof(params)); - if (!local->ops->conf_tx) - return; - local->wmm_acm = 0; for (; left >= 4; left -= 4, pos += 4) { int aci = (pos[0] >> 5) & 0x03; @@ -427,26 +424,26 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, int queue; switch (aci) { - case 1: + case 1: /* AC_BK */ queue = 3; if (acm) - local->wmm_acm |= BIT(0) | BIT(3); + local->wmm_acm |= BIT(1) | BIT(2); /* BK/- */ break; - case 2: + case 2: /* AC_VI */ queue = 1; if (acm) - local->wmm_acm |= BIT(4) | BIT(5); + local->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */ break; - case 3: + case 3: /* AC_VO */ queue = 0; if (acm) - local->wmm_acm |= BIT(6) | BIT(7); + local->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */ break; - case 0: + case 0: /* AC_BE */ default: queue = 2; if (acm) - local->wmm_acm |= BIT(1) | BIT(2); + local->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */ break; } @@ -460,9 +457,8 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, local->mdev->name, queue, aci, acm, params.aifs, params.cw_min, params.cw_max, params.txop); #endif - /* TODO: handle ACM (block TX, fallback to next lowest allowed - * AC for now) */ - if (local->ops->conf_tx(local_to_hw(local), queue, ¶ms)) { + if (local->ops->conf_tx && + local->ops->conf_tx(local_to_hw(local), queue, ¶ms)) { printk(KERN_DEBUG "%s: failed to set TX queue " "parameters for queue %d\n", local->mdev->name, queue); } @@ -1724,7 +1720,10 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata) local->int_scan_req.ssids[0].ssid_len = 0; else local->int_scan_req.ssids[0].ssid_len = ifmgd->ssid_len; - ieee80211_start_scan(sdata, &local->int_scan_req); + + if (ieee80211_start_scan(sdata, &local->int_scan_req)) + ieee80211_scan_failed(local); + ifmgd->state = IEEE80211_STA_MLME_AUTHENTICATE; set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request); } else { @@ -1761,7 +1760,14 @@ static void ieee80211_sta_work(struct work_struct *work) ifmgd->state != IEEE80211_STA_MLME_AUTHENTICATE && ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE && test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request)) { - ieee80211_start_scan(sdata, local->scan_req); + /* + * The call to ieee80211_start_scan can fail but ieee80211_request_scan + * (which queued ieee80211_sta_work) did not return an error. Thus, call + * ieee80211_scan_failed here if ieee80211_start_scan fails in order to + * notify the scan requester. + */ + if (ieee80211_start_scan(sdata, local->scan_req)) + ieee80211_scan_failed(local); return; } diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 0e81e1633a66..5030a3c87509 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -202,6 +202,18 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, return RX_QUEUED; } +void ieee80211_scan_failed(struct ieee80211_local *local) +{ + if (WARN_ON(!local->scan_req)) + return; + + /* notify cfg80211 about the failed scan */ + if (local->scan_req != &local->int_scan_req) + cfg80211_scan_done(local->scan_req, true); + + local->scan_req = NULL; +} + void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) { struct ieee80211_local *local = hw_to_local(hw); diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 093a4ab7f28b..0b8ad1f4ecdd 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c @@ -99,10 +99,13 @@ static u16 classify80211(struct ieee80211_local *local, struct sk_buff *skb) /* in case we are a client verify acm is not set for this ac */ while (unlikely(local->wmm_acm & BIT(skb->priority))) { if (wme_downgrade_ac(skb)) { - /* The old code would drop the packet in this - * case. + /* + * This should not really happen. The AP has marked all + * lower ACs to require admission control which is not + * a reasonable configuration. Allow the frame to be + * transmitted using AC_BK as a workaround. */ - return 0; + break; } } |