]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - net/mac80211/tx.c
Merge tag 'mac80211-next-for-davem-2019-04-26' of git://git.kernel.org/pub/scm/linux...
[linux.git] / net / mac80211 / tx.c
index 2e816dd67be72d161bf1959554d293f2f6725673..dd220b977025cb8149fb91af86a838e376037970 100644 (file)
@@ -1399,11 +1399,15 @@ static void ieee80211_txq_enqueue(struct ieee80211_local *local,
 {
        struct fq *fq = &local->fq;
        struct fq_tin *tin = &txqi->tin;
+       u32 flow_idx = fq_flow_idx(fq, skb);
 
        ieee80211_set_skb_enqueue_time(skb);
-       fq_tin_enqueue(fq, tin, skb,
+
+       spin_lock_bh(&fq->lock);
+       fq_tin_enqueue(fq, tin, flow_idx, skb,
                       fq_skb_free_func,
                       fq_flow_get_default_func);
+       spin_unlock_bh(&fq->lock);
 }
 
 static bool fq_vlan_filter_func(struct fq *fq, struct fq_tin *tin,
@@ -1590,7 +1594,6 @@ static bool ieee80211_queue_skb(struct ieee80211_local *local,
                                struct sta_info *sta,
                                struct sk_buff *skb)
 {
-       struct fq *fq = &local->fq;
        struct ieee80211_vif *vif;
        struct txq_info *txqi;
 
@@ -1608,9 +1611,7 @@ static bool ieee80211_queue_skb(struct ieee80211_local *local,
        if (!txqi)
                return false;
 
-       spin_lock_bh(&fq->lock);
        ieee80211_txq_enqueue(local, txqi, skb);
-       spin_unlock_bh(&fq->lock);
 
        schedule_and_wake_txq(local, txqi);
 
@@ -2431,6 +2432,7 @@ static int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,
  * @sdata: virtual interface to build the header for
  * @skb: the skb to build the header in
  * @info_flags: skb flags to set
+ * @ctrl_flags: info control flags to set
  *
  * This function takes the skb with 802.3 header and reformats the header to
  * the appropriate IEEE 802.11 header based on which interface the packet is
@@ -2446,7 +2448,7 @@ static int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,
  */
 static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
                                           struct sk_buff *skb, u32 info_flags,
-                                          struct sta_info *sta)
+                                          struct sta_info *sta, u32 ctrl_flags)
 {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_tx_info *info;
@@ -2470,6 +2472,11 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
        if (IS_ERR(sta))
                sta = NULL;
 
+#ifdef CONFIG_MAC80211_DEBUGFS
+       if (local->force_tx_status)
+               info_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
+#endif
+
        /* convert Ethernet header to proper 802.11 header (based on
         * operation mode) */
        ethertype = (skb->data[12] << 8) | skb->data[13];
@@ -2600,6 +2607,13 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
                        goto free;
                }
                band = chanctx_conf->def.chan->band;
+
+               /* For injected frames, fill RA right away as nexthop lookup
+                * will be skipped.
+                */
+               if ((ctrl_flags & IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP) &&
+                   is_zero_ether_addr(hdr.addr1))
+                       memcpy(hdr.addr1, skb->data, ETH_ALEN);
                break;
 #endif
        case NL80211_IFTYPE_STATION:
@@ -2818,6 +2832,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
        info->flags = info_flags;
        info->ack_frame_id = info_id;
        info->band = band;
+       info->control.flags = ctrl_flags;
 
        return skb;
  free:
@@ -3000,23 +3015,15 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
                switch (build.key->conf.cipher) {
                case WLAN_CIPHER_SUITE_CCMP:
                case WLAN_CIPHER_SUITE_CCMP_256:
-                       /* add fixed key ID */
-                       if (gen_iv) {
-                               (build.hdr + build.hdr_len)[3] =
-                                       0x20 | (build.key->conf.keyidx << 6);
+                       if (gen_iv)
                                build.pn_offs = build.hdr_len;
-                       }
                        if (gen_iv || iv_spc)
                                build.hdr_len += IEEE80211_CCMP_HDR_LEN;
                        break;
                case WLAN_CIPHER_SUITE_GCMP:
                case WLAN_CIPHER_SUITE_GCMP_256:
-                       /* add fixed key ID */
-                       if (gen_iv) {
-                               (build.hdr + build.hdr_len)[3] =
-                                       0x20 | (build.key->conf.keyidx << 6);
+                       if (gen_iv)
                                build.pn_offs = build.hdr_len;
-                       }
                        if (gen_iv || iv_spc)
                                build.hdr_len += IEEE80211_GCMP_HDR_LEN;
                        break;
@@ -3222,6 +3229,7 @@ static bool ieee80211_amsdu_aggregate(struct ieee80211_sub_if_data *sdata,
        int max_frags = local->hw.max_tx_fragments;
        int max_amsdu_len = sta->sta.max_amsdu_len;
        int orig_truesize;
+       u32 flow_idx;
        __be16 len;
        void *data;
        bool ret = false;
@@ -3250,6 +3258,8 @@ static bool ieee80211_amsdu_aggregate(struct ieee80211_sub_if_data *sdata,
                max_amsdu_len = min_t(int, max_amsdu_len,
                                      sta->sta.max_tid_amsdu_len[tid]);
 
+       flow_idx = fq_flow_idx(fq, skb);
+
        spin_lock_bh(&fq->lock);
 
        /* TODO: Ideally aggregation should be done on dequeue to remain
@@ -3257,7 +3267,8 @@ static bool ieee80211_amsdu_aggregate(struct ieee80211_sub_if_data *sdata,
         */
 
        tin = &txqi->tin;
-       flow = fq_flow_classify(fq, tin, skb, fq_flow_get_default_func);
+       flow = fq_flow_classify(fq, tin, flow_idx, skb,
+                               fq_flow_get_default_func);
        head = skb_peek_tail(&flow->queue);
        if (!head || skb_is_gso(head))
                goto out;
@@ -3386,6 +3397,7 @@ static void ieee80211_xmit_fast_finish(struct ieee80211_sub_if_data *sdata,
                        pn = atomic64_inc_return(&key->conf.tx_pn);
                        crypto_hdr[0] = pn;
                        crypto_hdr[1] = pn >> 8;
+                       crypto_hdr[3] = 0x20 | (key->conf.keyidx << 6);
                        crypto_hdr[4] = pn >> 16;
                        crypto_hdr[5] = pn >> 24;
                        crypto_hdr[6] = pn >> 32;
@@ -3478,6 +3490,11 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
                      (tid_tx ? IEEE80211_TX_CTL_AMPDU : 0);
        info->control.flags = IEEE80211_TX_CTRL_FAST_XMIT;
 
+#ifdef CONFIG_MAC80211_DEBUGFS
+       if (local->force_tx_status)
+               info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
+#endif
+
        if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
                tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
                *ieee80211_get_qos_ctl(hdr) = tid;
@@ -3533,6 +3550,7 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
        ieee80211_tx_result r;
        struct ieee80211_vif *vif = txq->vif;
 
+begin:
        spin_lock_bh(&fq->lock);
 
        if (test_bit(IEEE80211_TXQ_STOP, &txqi->flags) ||
@@ -3549,11 +3567,12 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
        if (skb)
                goto out;
 
-begin:
        skb = fq_tin_dequeue(fq, tin, fq_tin_dequeue_func);
        if (!skb)
                goto out;
 
+       spin_unlock_bh(&fq->lock);
+
        hdr = (struct ieee80211_hdr *)skb->data;
        info = IEEE80211_SKB_CB(skb);
 
@@ -3598,8 +3617,11 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
 
                skb = __skb_dequeue(&tx.skbs);
 
-               if (!skb_queue_empty(&tx.skbs))
+               if (!skb_queue_empty(&tx.skbs)) {
+                       spin_lock_bh(&fq->lock);
                        skb_queue_splice_tail(&tx.skbs, &txqi->frags);
+                       spin_unlock_bh(&fq->lock);
+               }
        }
 
        if (skb_has_frag_list(skb) &&
@@ -3638,6 +3660,7 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
        }
 
        IEEE80211_SKB_CB(skb)->control.vif = vif;
+       return skb;
 
 out:
        spin_unlock_bh(&fq->lock);
@@ -3783,9 +3806,11 @@ EXPORT_SYMBOL(ieee80211_txq_schedule_start);
 
 void __ieee80211_subif_start_xmit(struct sk_buff *skb,
                                  struct net_device *dev,
-                                 u32 info_flags)
+                                 u32 info_flags,
+                                 u32 ctrl_flags)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_local *local = sdata->local;
        struct sta_info *sta;
        struct sk_buff *next;
 
@@ -3799,7 +3824,15 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
        if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
                goto out_free;
 
-       if (!IS_ERR_OR_NULL(sta)) {
+       if (IS_ERR(sta))
+               sta = NULL;
+
+       if (local->ops->wake_tx_queue) {
+               u16 queue = __ieee80211_select_queue(sdata, sta, skb);
+               skb_set_queue_mapping(skb, queue);
+       }
+
+       if (sta) {
                struct ieee80211_fast_tx *fast_tx;
 
                sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift);
@@ -3848,7 +3881,8 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
                skb->prev = NULL;
                skb->next = NULL;
 
-               skb = ieee80211_build_hdr(sdata, skb, info_flags, sta);
+               skb = ieee80211_build_hdr(sdata, skb, info_flags,
+                                         sta, ctrl_flags);
                if (IS_ERR(skb))
                        goto out;
 
@@ -3988,9 +4022,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                __skb_queue_head_init(&queue);
                ieee80211_convert_to_unicast(skb, dev, &queue);
                while ((skb = __skb_dequeue(&queue)))
-                       __ieee80211_subif_start_xmit(skb, dev, 0);
+                       __ieee80211_subif_start_xmit(skb, dev, 0, 0);
        } else {
-               __ieee80211_subif_start_xmit(skb, dev, 0);
+               __ieee80211_subif_start_xmit(skb, dev, 0, 0);
        }
 
        return NETDEV_TX_OK;
@@ -4015,7 +4049,7 @@ ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
                goto out;
        }
 
-       skb = ieee80211_build_hdr(sdata, skb, info_flags, sta);
+       skb = ieee80211_build_hdr(sdata, skb, info_flags, sta, 0);
        if (IS_ERR(skb))
                goto out;
 
@@ -5052,7 +5086,36 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
        skb_reset_mac_header(skb);
 
        local_bh_disable();
-       __ieee80211_subif_start_xmit(skb, skb->dev, flags);
+       __ieee80211_subif_start_xmit(skb, skb->dev, flags, 0);
+       local_bh_enable();
+
+       return 0;
+}
+
+int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
+                             const u8 *buf, size_t len)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_local *local = sdata->local;
+       struct sk_buff *skb;
+
+       skb = dev_alloc_skb(local->hw.extra_tx_headroom + len +
+                           30 + /* header size */
+                           18); /* 11s header size */
+       if (!skb)
+               return -ENOMEM;
+
+       skb_reserve(skb, local->hw.extra_tx_headroom);
+       skb_put_data(skb, buf, len);
+
+       skb->dev = dev;
+       skb->protocol = htons(ETH_P_802_3);
+       skb_reset_network_header(skb);
+       skb_reset_mac_header(skb);
+
+       local_bh_disable();
+       __ieee80211_subif_start_xmit(skb, skb->dev, 0,
+                                    IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP);
        local_bh_enable();
 
        return 0;