mac80211: Indicate basic rates when adding rate IEs
[deliverable/linux.git] / net / mac80211 / tx.c
index e05667cd5e766057c22770670834e6f2b19e3301..4109ec7999a372206fc217bc853917a05cbd6727 100644 (file)
@@ -226,13 +226,13 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
         * have correct qos tag for some reason, due the network or the
         * peer application.
         *
-        * Note: local->uapsd_queues access is racy here. If the value is
+        * Note: ifmgd->uapsd_queues access is racy here. If the value is
         * changed via debugfs, user needs to reassociate manually to have
         * everything in sync.
         */
-       if ((ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED)
-           && (local->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
-           && skb_get_queue_mapping(tx->skb) == 0)
+       if ((ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED) &&
+           (ifmgd->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) &&
+           skb_get_queue_mapping(tx->skb) == IEEE80211_AC_VO)
                return TX_CONTINUE;
 
        if (local->hw.conf.flags & IEEE80211_CONF_PS) {
@@ -448,18 +448,23 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
        struct ieee80211_local *local = tx->local;
 
-       if (unlikely(!sta ||
-                    ieee80211_is_probe_resp(hdr->frame_control) ||
-                    ieee80211_is_auth(hdr->frame_control) ||
-                    ieee80211_is_assoc_resp(hdr->frame_control) ||
-                    ieee80211_is_reassoc_resp(hdr->frame_control)))
+       if (unlikely(!sta))
                return TX_CONTINUE;
 
        if (unlikely((test_sta_flag(sta, WLAN_STA_PS_STA) ||
                      test_sta_flag(sta, WLAN_STA_PS_DRIVER)) &&
-                    !(info->flags & IEEE80211_TX_CTL_POLL_RESPONSE))) {
+                    !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) {
                int ac = skb_get_queue_mapping(tx->skb);
 
+               /* only deauth, disassoc and action are bufferable MMPDUs */
+               if (ieee80211_is_mgmt(hdr->frame_control) &&
+                   !ieee80211_is_deauth(hdr->frame_control) &&
+                   !ieee80211_is_disassoc(hdr->frame_control) &&
+                   !ieee80211_is_action(hdr->frame_control)) {
+                       info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
+                       return TX_CONTINUE;
+               }
+
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
                printk(KERN_DEBUG "STA %pM aid %d: PS buffer for AC %d\n",
                       sta->sta.addr, sta->sta.aid, ac);
@@ -625,7 +630,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
                         tx->local->hw.wiphy->frag_threshold);
 
        /* set up the tx rate control struct we give the RC algo */
-       txrc.hw = local_to_hw(tx->local);
+       txrc.hw = &tx->local->hw;
        txrc.sband = sband;
        txrc.bss_conf = &tx->sdata->vif.bss_conf;
        txrc.skb = tx->skb;
@@ -635,6 +640,9 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
                txrc.max_rate_idx = -1;
        else
                txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
+       memcpy(txrc.rate_idx_mcs_mask,
+              tx->sdata->rc_rateidx_mcs_mask[tx->channel->band],
+              sizeof(txrc.rate_idx_mcs_mask));
        txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP ||
                    tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
                    tx->sdata->vif.type == NL80211_IFTYPE_ADHOC);
@@ -1057,6 +1065,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
 {
        bool queued = false;
        bool reset_agg_timer = false;
+       struct sk_buff *purge_skb = NULL;
 
        if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
                info->flags |= IEEE80211_TX_CTL_AMPDU;
@@ -1098,14 +1107,18 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
                        info->control.vif = &tx->sdata->vif;
                        info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
                        __skb_queue_tail(&tid_tx->pending, skb);
+                       if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER)
+                               purge_skb = __skb_dequeue(&tid_tx->pending);
                }
                spin_unlock(&tx->sta->lock);
+
+               if (purge_skb)
+                       dev_kfree_skb(purge_skb);
        }
 
        /* reset session timer */
        if (reset_agg_timer && tid_tx->timeout)
-               mod_timer(&tid_tx->session_timer,
-                         TU_TO_EXP_TIME(tid_tx->timeout));
+               tid_tx->last_tx = jiffies;
 
        return queued;
 }
@@ -1454,12 +1467,12 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
 
        if (ieee80211_vif_is_mesh(&sdata->vif) &&
            ieee80211_is_data(hdr->frame_control) &&
-               !is_multicast_ether_addr(hdr->addr1))
-                       if (mesh_nexthop_resolve(skb, sdata)) {
-                               /* skb queued: don't free */
-                               rcu_read_unlock();
-                               return;
-                       }
+           !is_multicast_ether_addr(hdr->addr1) &&
+           mesh_nexthop_resolve(skb, sdata)) {
+               /* skb queued: don't free */
+               rcu_read_unlock();
+               return;
+       }
 
        ieee80211_set_qos_hdr(sdata, skb);
        ieee80211_tx(sdata, skb, false);
@@ -1915,7 +1928,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                wme_sta = true;
 
        /* receiver and we are QoS enabled, use a QoS type frame */
-       if (wme_sta && local->hw.queues >= 4) {
+       if (wme_sta && local->hw.queues >= IEEE80211_NUM_ACS) {
                fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
                hdrlen += 2;
        }
@@ -2203,7 +2216,8 @@ void ieee80211_tx_pending(unsigned long data)
 
 /* functions for drivers to get certain frames */
 
-static void ieee80211_beacon_add_tim(struct ieee80211_if_ap *bss,
+static void ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
+                                    struct ieee80211_if_ap *bss,
                                     struct sk_buff *skb,
                                     struct beacon_data *beacon)
 {
@@ -2220,7 +2234,7 @@ static void ieee80211_beacon_add_tim(struct ieee80211_if_ap *bss,
                                          IEEE80211_MAX_AID+1);
 
        if (bss->dtim_count == 0)
-               bss->dtim_count = beacon->dtim_period - 1;
+               bss->dtim_count = sdata->vif.bss_conf.dtim_period - 1;
        else
                bss->dtim_count--;
 
@@ -2228,7 +2242,7 @@ static void ieee80211_beacon_add_tim(struct ieee80211_if_ap *bss,
        *pos++ = WLAN_EID_TIM;
        *pos++ = 4;
        *pos++ = bss->dtim_count;
-       *pos++ = beacon->dtim_period;
+       *pos++ = sdata->vif.bss_conf.dtim_period;
 
        if (bss->dtim_count == 0 && !skb_queue_empty(&bss->ps_bc_buf))
                aid0 = 1;
@@ -2321,12 +2335,14 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                         * of the tim bitmap in mac80211 and the driver.
                         */
                        if (local->tim_in_locked_section) {
-                               ieee80211_beacon_add_tim(ap, skb, beacon);
+                               ieee80211_beacon_add_tim(sdata, ap, skb,
+                                                        beacon);
                        } else {
                                unsigned long flags;
 
                                spin_lock_irqsave(&local->tim_lock, flags);
-                               ieee80211_beacon_add_tim(ap, skb, beacon);
+                               ieee80211_beacon_add_tim(sdata, ap, skb,
+                                                        beacon);
                                spin_unlock_irqrestore(&local->tim_lock, flags);
                        }
 
@@ -2357,6 +2373,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                                                 IEEE80211_STYPE_BEACON);
        } else if (ieee80211_vif_is_mesh(&sdata->vif)) {
                struct ieee80211_mgmt *mgmt;
+               struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
                u8 *pos;
                int hdr_len = offsetof(struct ieee80211_mgmt, u.beacon) +
                              sizeof(mgmt->u.beacon);
@@ -2366,6 +2383,10 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                        goto out;
 #endif
 
+               if (ifmsh->sync_ops)
+                       ifmsh->sync_ops->adjust_tbtt(
+                                               sdata);
+
                skb = dev_alloc_skb(local->tx_headroom +
                                    hdr_len +
                                    2 + /* NULL SSID */
@@ -2373,7 +2394,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                                    2 + 3 + /* DS params */
                                    2 + (IEEE80211_MAX_SUPP_RATES - 8) +
                                    2 + sizeof(struct ieee80211_ht_cap) +
-                                   2 + sizeof(struct ieee80211_ht_info) +
+                                   2 + sizeof(struct ieee80211_ht_operation) +
                                    2 + sdata->u.mesh.mesh_id_len +
                                    2 + sizeof(struct ieee80211_meshconf_ie) +
                                    sdata->u.mesh.ie_len);
@@ -2397,12 +2418,12 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                *pos++ = WLAN_EID_SSID;
                *pos++ = 0x0;
 
-               if (ieee80211_add_srates_ie(&sdata->vif, skb) ||
+               if (ieee80211_add_srates_ie(&sdata->vif, skb, true) ||
                    mesh_add_ds_params_ie(skb, sdata) ||
-                   ieee80211_add_ext_srates_ie(&sdata->vif, skb) ||
+                   ieee80211_add_ext_srates_ie(&sdata->vif, skb, true) ||
                    mesh_add_rsn_ie(skb, sdata) ||
                    mesh_add_ht_cap_ie(skb, sdata) ||
-                   mesh_add_ht_info_ie(skb, sdata) ||
+                   mesh_add_ht_oper_ie(skb, sdata) ||
                    mesh_add_meshid_ie(skb, sdata) ||
                    mesh_add_meshconf_ie(skb, sdata) ||
                    mesh_add_vendor_ies(skb, sdata)) {
@@ -2431,6 +2452,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                txrc.max_rate_idx = -1;
        else
                txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
+       memcpy(txrc.rate_idx_mcs_mask, sdata->rc_rateidx_mcs_mask[band],
+              sizeof(txrc.rate_idx_mcs_mask));
        txrc.bss = true;
        rate_control_get_rate(sdata, NULL, &txrc);
 
@@ -2584,7 +2607,7 @@ struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
        pos = skb_put(skb, ie_ssid_len);
        *pos++ = WLAN_EID_SSID;
        *pos++ = ssid_len;
-       if (ssid)
+       if (ssid_len)
                memcpy(pos, ssid, ssid_len);
        pos += ssid_len;
 
This page took 0.246244 seconds and 5 git commands to generate.