net: clear heap allocations for privileged ethtool actions
[firefly-linux-kernel-4.4.55.git] / net / mac80211 / mlme.c
index 97a278a2f48ee1a88b4cc1e585ac8e2a4e19ce45..5bea319e3e54b7d17cad18f4a71a353b3b5b6f68 100644 (file)
@@ -269,12 +269,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
        if (wk->bss->wmm_used)
                wmm = 1;
 
-       /* get all rates supported by the device and the AP as
-        * some APs don't like getting a superset of their rates
-        * in the association request (e.g. D-Link DAP 1353 in
-        * b-only mode) */
-       rates_len = ieee80211_compatible_rates(wk->bss, sband, &rates);
-
        if ((wk->bss->cbss.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
            (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
                capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
@@ -309,6 +303,17 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
        *pos++ = wk->ssid_len;
        memcpy(pos, wk->ssid, wk->ssid_len);
 
+       if (wk->bss->supp_rates_len) {
+               /* get all rates supported by the device and the AP as
+                * some APs don't like getting a superset of their rates
+                * in the association request (e.g. D-Link DAP 1353 in
+                * b-only mode) */
+               rates_len = ieee80211_compatible_rates(wk->bss, sband, &rates);
+       } else {
+               rates = ~0;
+               rates_len = sband->n_bitrates;
+       }
+
        /* add all rates which were marked to be used above */
        supp_rates_len = rates_len;
        if (supp_rates_len > 8)
@@ -650,8 +655,11 @@ static void ieee80211_enable_ps(struct ieee80211_local *local,
        } else {
                if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
                        ieee80211_send_nullfunc(local, sdata, 1);
-               conf->flags |= IEEE80211_CONF_PS;
-               ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+
+               if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) {
+                       conf->flags |= IEEE80211_CONF_PS;
+                       ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+               }
        }
 }
 
@@ -742,6 +750,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
                container_of(work, struct ieee80211_local,
                             dynamic_ps_enable_work);
        struct ieee80211_sub_if_data *sdata = local->ps_sdata;
+       struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
        /* can only happen when PS was just disabled anyway */
        if (!sdata)
@@ -750,11 +759,16 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
        if (local->hw.conf.flags & IEEE80211_CONF_PS)
                return;
 
-       if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
+       if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
+           (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)))
                ieee80211_send_nullfunc(local, sdata, 1);
 
-       local->hw.conf.flags |= IEEE80211_CONF_PS;
-       ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+       if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) ||
+           (ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) {
+               ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
+               local->hw.conf.flags |= IEEE80211_CONF_PS;
+               ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+       }
 }
 
 void ieee80211_dynamic_ps_timer(unsigned long data)
@@ -904,6 +918,14 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
        sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL |
                                IEEE80211_STA_BEACON_POLL);
 
+       /*
+        * Always handle WMM once after association regardless
+        * of the first value the AP uses. Setting -1 here has
+        * that effect because the AP values is an unsigned
+        * 4-bit value.
+        */
+       sdata->u.mgd.wmm_last_param_set = -1;
+
        ieee80211_led_assoc(local, 1);
 
        sdata->vif.bss_conf.assoc = 1;
@@ -1388,8 +1410,8 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
 
        reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
 
-       printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n",
-                       sdata->dev->name, reason_code);
+       printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n",
+                       sdata->dev->name, mgmt->sa, reason_code);
 
        ieee80211_set_disassoc(sdata, false);
        return RX_MGMT_CFG80211_DISASSOC;
@@ -1457,8 +1479,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
        if (status_code != WLAN_STATUS_SUCCESS) {
                printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
                       sdata->dev->name, status_code);
-               list_del(&wk->list);
-               kfree(wk);
+               wk->state = IEEE80211_MGD_STATE_IDLE;
                return RX_MGMT_CFG80211_ASSOC;
        }
 
@@ -1675,7 +1696,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
 
        /* direct probe may be part of the association flow */
        if (wk && wk->state == IEEE80211_MGD_STATE_PROBE) {
-               printk(KERN_DEBUG "%s direct probe responded\n",
+               printk(KERN_DEBUG "%s: direct probe responded\n",
                       sdata->dev->name);
                wk->tries = 0;
                wk->state = IEEE80211_MGD_STATE_AUTH;
@@ -1946,7 +1967,9 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
                        rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
                        break;
                case IEEE80211_STYPE_ACTION:
-                       /* XXX: differentiate, can only happen for CSA now! */
+                       if (mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT)
+                               break;
+
                        ieee80211_sta_process_chanswitch(sdata,
                                        &mgmt->u.action.u.chan_switch.sw_elem,
                                        ifmgd->associated);
@@ -2449,6 +2472,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
        list_add(&wk->list, &ifmgd->work_list);
 
        ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N;
+       ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
 
        for (i = 0; i < req->crypto.n_ciphers_pairwise; i++)
                if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 ||
@@ -2502,9 +2526,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_mgd_work *wk;
        const u8 *bssid = NULL;
 
-       printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n",
-              sdata->dev->name, req->reason_code);
-
        mutex_lock(&ifmgd->mtx);
 
        if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) {
@@ -2532,6 +2553,9 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
 
        mutex_unlock(&ifmgd->mtx);
 
+       printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n",
+              sdata->dev->name, bssid, req->reason_code);
+
        ieee80211_send_deauth_disassoc(sdata, bssid,
                        IEEE80211_STYPE_DEAUTH, req->reason_code,
                        cookie);
@@ -2545,9 +2569,6 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
 {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
-       printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n",
-              sdata->dev->name, req->reason_code);
-
        mutex_lock(&ifmgd->mtx);
 
        /*
@@ -2561,6 +2582,9 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
                return -ENOLINK;
        }
 
+       printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n",
+              sdata->dev->name, req->bss->bssid, req->reason_code);
+
        ieee80211_set_disassoc(sdata, false);
 
        mutex_unlock(&ifmgd->mtx);