1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2e2ebc74dSJohannes Berg /* 3e2ebc74dSJohannes Berg * Copyright 2002-2005, Instant802 Networks, Inc. 4e2ebc74dSJohannes Berg * Copyright 2005-2006, Devicescape Software, Inc. 5e2ebc74dSJohannes Berg * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 6e2ebc74dSJohannes Berg * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> 7d98ad83eSJohannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH 873bc9e0aSJohannes Berg * Copyright (C) 2018-2021 Intel Corporation 9e2ebc74dSJohannes Berg * 10e2ebc74dSJohannes Berg * Transmit and frame generation functions. 11e2ebc74dSJohannes Berg */ 12e2ebc74dSJohannes Berg 13e2ebc74dSJohannes Berg #include <linux/kernel.h> 14e2ebc74dSJohannes Berg #include <linux/slab.h> 15e2ebc74dSJohannes Berg #include <linux/skbuff.h> 16ebceec86SMichael Braun #include <linux/if_vlan.h> 17e2ebc74dSJohannes Berg #include <linux/etherdevice.h> 18e2ebc74dSJohannes Berg #include <linux/bitmap.h> 19d4e46a3dSJohannes Berg #include <linux/rcupdate.h> 20bc3b2d7fSPaul Gortmaker #include <linux/export.h> 21881d966bSEric W. Biederman #include <net/net_namespace.h> 22e2ebc74dSJohannes Berg #include <net/ieee80211_radiotap.h> 23e2ebc74dSJohannes Berg #include <net/cfg80211.h> 24e2ebc74dSJohannes Berg #include <net/mac80211.h> 255caa328eSMichal Kazior #include <net/codel.h> 265caa328eSMichal Kazior #include <net/codel_impl.h> 27e2ebc74dSJohannes Berg #include <asm/unaligned.h> 28fa962b92SMichal Kazior #include <net/fq_impl.h> 29e2ebc74dSJohannes Berg 30e2ebc74dSJohannes Berg #include "ieee80211_i.h" 3124487981SJohannes Berg #include "driver-ops.h" 322c8dccc7SJohannes Berg #include "led.h" 3333b64eb2SLuis Carlos Cobo #include "mesh.h" 34e2ebc74dSJohannes Berg #include "wep.h" 35e2ebc74dSJohannes Berg #include "wpa.h" 36e2ebc74dSJohannes Berg #include "wme.h" 372c8dccc7SJohannes Berg #include "rate.h" 38e2ebc74dSJohannes Berg 39e2ebc74dSJohannes Berg /* misc utils */ 40e2ebc74dSJohannes Berg 41252b86c4SJohannes Berg static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, 42252b86c4SJohannes Berg struct sk_buff *skb, int group_addr, 43e2ebc74dSJohannes Berg int next_frag_len) 44e2ebc74dSJohannes Berg { 452103dec1SSimon Wunderlich int rate, mrate, erp, dur, i, shift = 0; 462e92e6f2SJohannes Berg struct ieee80211_rate *txrate; 47e2ebc74dSJohannes Berg struct ieee80211_local *local = tx->local; 488318d78aSJohannes Berg struct ieee80211_supported_band *sband; 49358c8d9dSHarvey Harrison struct ieee80211_hdr *hdr; 50252b86c4SJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 512103dec1SSimon Wunderlich struct ieee80211_chanctx_conf *chanctx_conf; 522103dec1SSimon Wunderlich u32 rate_flags = 0; 532103dec1SSimon Wunderlich 5495cd470cSFelix Fietkau /* assume HW handles this */ 5595cd470cSFelix Fietkau if (tx->rate.flags & (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_VHT_MCS)) 5695cd470cSFelix Fietkau return 0; 5795cd470cSFelix Fietkau 582103dec1SSimon Wunderlich rcu_read_lock(); 592103dec1SSimon Wunderlich chanctx_conf = rcu_dereference(tx->sdata->vif.chanctx_conf); 602103dec1SSimon Wunderlich if (chanctx_conf) { 612103dec1SSimon Wunderlich shift = ieee80211_chandef_get_shift(&chanctx_conf->def); 622103dec1SSimon Wunderlich rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def); 632103dec1SSimon Wunderlich } 642103dec1SSimon Wunderlich rcu_read_unlock(); 65e6a9854bSJohannes Berg 66e6a9854bSJohannes Berg /* uh huh? */ 670d528d85SFelix Fietkau if (WARN_ON_ONCE(tx->rate.idx < 0)) 68e6a9854bSJohannes Berg return 0; 69e2ebc74dSJohannes Berg 702d56577bSJohannes Berg sband = local->hw.wiphy->bands[info->band]; 710d528d85SFelix Fietkau txrate = &sband->bitrates[tx->rate.idx]; 728318d78aSJohannes Berg 738318d78aSJohannes Berg erp = txrate->flags & IEEE80211_RATE_ERP_G; 74e2ebc74dSJohannes Berg 7589b8c02aSThomas Pedersen /* device is expected to do this */ 7689b8c02aSThomas Pedersen if (sband->band == NL80211_BAND_S1GHZ) 7789b8c02aSThomas Pedersen return 0; 7889b8c02aSThomas Pedersen 79e2ebc74dSJohannes Berg /* 80e2ebc74dSJohannes Berg * data and mgmt (except PS Poll): 81e2ebc74dSJohannes Berg * - during CFP: 32768 82e2ebc74dSJohannes Berg * - during contention period: 83e2ebc74dSJohannes Berg * if addr1 is group address: 0 84e2ebc74dSJohannes Berg * if more fragments = 0 and addr1 is individual address: time to 85e2ebc74dSJohannes Berg * transmit one ACK plus SIFS 86e2ebc74dSJohannes Berg * if more fragments = 1 and addr1 is individual address: time to 87e2ebc74dSJohannes Berg * transmit next fragment plus 2 x ACK plus 3 x SIFS 88e2ebc74dSJohannes Berg * 89e2ebc74dSJohannes Berg * IEEE 802.11, 9.6: 90e2ebc74dSJohannes Berg * - control response frame (CTS or ACK) shall be transmitted using the 91e2ebc74dSJohannes Berg * same rate as the immediately previous frame in the frame exchange 92e2ebc74dSJohannes Berg * sequence, if this rate belongs to the PHY mandatory rates, or else 93e2ebc74dSJohannes Berg * at the highest possible rate belonging to the PHY rates in the 94e2ebc74dSJohannes Berg * BSSBasicRateSet 95e2ebc74dSJohannes Berg */ 96252b86c4SJohannes Berg hdr = (struct ieee80211_hdr *)skb->data; 97358c8d9dSHarvey Harrison if (ieee80211_is_ctl(hdr->frame_control)) { 98e2ebc74dSJohannes Berg /* TODO: These control frames are not currently sent by 99ccd7b362SJohannes Berg * mac80211, but should they be implemented, this function 100e2ebc74dSJohannes Berg * needs to be updated to support duration field calculation. 101e2ebc74dSJohannes Berg * 102e2ebc74dSJohannes Berg * RTS: time needed to transmit pending data/mgmt frame plus 103e2ebc74dSJohannes Berg * one CTS frame plus one ACK frame plus 3 x SIFS 104e2ebc74dSJohannes Berg * CTS: duration of immediately previous RTS minus time 105e2ebc74dSJohannes Berg * required to transmit CTS and its SIFS 106e2ebc74dSJohannes Berg * ACK: 0 if immediately previous directed data/mgmt had 107e2ebc74dSJohannes Berg * more=0, with more=1 duration in ACK frame is duration 108e2ebc74dSJohannes Berg * from previous frame minus time needed to transmit ACK 109e2ebc74dSJohannes Berg * and its SIFS 110e2ebc74dSJohannes Berg * PS Poll: BIT(15) | BIT(14) | aid 111e2ebc74dSJohannes Berg */ 112e2ebc74dSJohannes Berg return 0; 113e2ebc74dSJohannes Berg } 114e2ebc74dSJohannes Berg 115e2ebc74dSJohannes Berg /* data/mgmt */ 116e2ebc74dSJohannes Berg if (0 /* FIX: data/mgmt during CFP */) 11703f93c3dSJohannes Berg return cpu_to_le16(32768); 118e2ebc74dSJohannes Berg 119e2ebc74dSJohannes Berg if (group_addr) /* Group address as the destination - no ACK */ 120e2ebc74dSJohannes Berg return 0; 121e2ebc74dSJohannes Berg 122e2ebc74dSJohannes Berg /* Individual destination address: 123e2ebc74dSJohannes Berg * IEEE 802.11, Ch. 9.6 (after IEEE 802.11g changes) 124e2ebc74dSJohannes Berg * CTS and ACK frames shall be transmitted using the highest rate in 125e2ebc74dSJohannes Berg * basic rate set that is less than or equal to the rate of the 126e2ebc74dSJohannes Berg * immediately previous frame and that is using the same modulation 127e2ebc74dSJohannes Berg * (CCK or OFDM). If no basic rate set matches with these requirements, 128e2ebc74dSJohannes Berg * the highest mandatory rate of the PHY that is less than or equal to 129e2ebc74dSJohannes Berg * the rate of the previous frame is used. 130e2ebc74dSJohannes Berg * Mandatory rates for IEEE 802.11g PHY: 1, 2, 5.5, 11, 6, 12, 24 Mbps 131e2ebc74dSJohannes Berg */ 132e2ebc74dSJohannes Berg rate = -1; 1338318d78aSJohannes Berg /* use lowest available if everything fails */ 1348318d78aSJohannes Berg mrate = sband->bitrates[0].bitrate; 1358318d78aSJohannes Berg for (i = 0; i < sband->n_bitrates; i++) { 1368318d78aSJohannes Berg struct ieee80211_rate *r = &sband->bitrates[i]; 1378318d78aSJohannes Berg 1388318d78aSJohannes Berg if (r->bitrate > txrate->bitrate) 139e2ebc74dSJohannes Berg break; 140e2ebc74dSJohannes Berg 1412103dec1SSimon Wunderlich if ((rate_flags & r->flags) != rate_flags) 1422103dec1SSimon Wunderlich continue; 1432103dec1SSimon Wunderlich 144bda3933aSJohannes Berg if (tx->sdata->vif.bss_conf.basic_rates & BIT(i)) 1452103dec1SSimon Wunderlich rate = DIV_ROUND_UP(r->bitrate, 1 << shift); 146e2ebc74dSJohannes Berg 1478318d78aSJohannes Berg switch (sband->band) { 14857fbcce3SJohannes Berg case NL80211_BAND_2GHZ: { 1498318d78aSJohannes Berg u32 flag; 1508318d78aSJohannes Berg if (tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) 1518318d78aSJohannes Berg flag = IEEE80211_RATE_MANDATORY_G; 1528318d78aSJohannes Berg else 1538318d78aSJohannes Berg flag = IEEE80211_RATE_MANDATORY_B; 1548318d78aSJohannes Berg if (r->flags & flag) 1558318d78aSJohannes Berg mrate = r->bitrate; 1568318d78aSJohannes Berg break; 1578318d78aSJohannes Berg } 15857fbcce3SJohannes Berg case NL80211_BAND_5GHZ: 159c5b9a7f8SArend van Spriel case NL80211_BAND_6GHZ: 1608318d78aSJohannes Berg if (r->flags & IEEE80211_RATE_MANDATORY_A) 1618318d78aSJohannes Berg mrate = r->bitrate; 1628318d78aSJohannes Berg break; 163df78a0c0SThomas Pedersen case NL80211_BAND_S1GHZ: 16457fbcce3SJohannes Berg case NL80211_BAND_60GHZ: 1653a0c52a6SVladimir Kondratiev /* TODO, for now fall through */ 16657fbcce3SJohannes Berg case NUM_NL80211_BANDS: 1678318d78aSJohannes Berg WARN_ON(1); 1688318d78aSJohannes Berg break; 1698318d78aSJohannes Berg } 170e2ebc74dSJohannes Berg } 171e2ebc74dSJohannes Berg if (rate == -1) { 172e2ebc74dSJohannes Berg /* No matching basic rate found; use highest suitable mandatory 173e2ebc74dSJohannes Berg * PHY rate */ 1742103dec1SSimon Wunderlich rate = DIV_ROUND_UP(mrate, 1 << shift); 175e2ebc74dSJohannes Berg } 176e2ebc74dSJohannes Berg 1776674f210SSimon Wunderlich /* Don't calculate ACKs for QoS Frames with NoAck Policy set */ 1786674f210SSimon Wunderlich if (ieee80211_is_data_qos(hdr->frame_control) && 179c26a0e10SClaudio Pisa *(ieee80211_get_qos_ctl(hdr)) & IEEE80211_QOS_CTL_ACK_POLICY_NOACK) 1806674f210SSimon Wunderlich dur = 0; 1816674f210SSimon Wunderlich else 182e2ebc74dSJohannes Berg /* Time needed to transmit ACK 183e2ebc74dSJohannes Berg * (10 bytes + 4-byte FCS = 112 bits) plus SIFS; rounded up 184e2ebc74dSJohannes Berg * to closest integer */ 1854ee73f33SMichal Kazior dur = ieee80211_frame_duration(sband->band, 10, rate, erp, 186438b61b7SSimon Wunderlich tx->sdata->vif.bss_conf.use_short_preamble, 187438b61b7SSimon Wunderlich shift); 188e2ebc74dSJohannes Berg 189e2ebc74dSJohannes Berg if (next_frag_len) { 190e2ebc74dSJohannes Berg /* Frame is fragmented: duration increases with time needed to 191e2ebc74dSJohannes Berg * transmit next fragment plus ACK and 2 x SIFS. */ 192e2ebc74dSJohannes Berg dur *= 2; /* ACK + SIFS */ 193e2ebc74dSJohannes Berg /* next fragment */ 1944ee73f33SMichal Kazior dur += ieee80211_frame_duration(sband->band, next_frag_len, 1958318d78aSJohannes Berg txrate->bitrate, erp, 196438b61b7SSimon Wunderlich tx->sdata->vif.bss_conf.use_short_preamble, 197438b61b7SSimon Wunderlich shift); 198e2ebc74dSJohannes Berg } 199e2ebc74dSJohannes Berg 20003f93c3dSJohannes Berg return cpu_to_le16(dur); 201e2ebc74dSJohannes Berg } 202e2ebc74dSJohannes Berg 203e2ebc74dSJohannes Berg /* tx handlers */ 2045c1b98a5SKalle Valo static ieee80211_tx_result debug_noinline 2055c1b98a5SKalle Valo ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx) 2065c1b98a5SKalle Valo { 2075c1b98a5SKalle Valo struct ieee80211_local *local = tx->local; 2080c74211dSKalle Valo struct ieee80211_if_managed *ifmgd; 20994a5b3acSAndrei Otcheretianski struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); 2105c1b98a5SKalle Valo 2115c1b98a5SKalle Valo /* driver doesn't support power save */ 21230686bf7SJohannes Berg if (!ieee80211_hw_check(&local->hw, SUPPORTS_PS)) 2135c1b98a5SKalle Valo return TX_CONTINUE; 2145c1b98a5SKalle Valo 2155c1b98a5SKalle Valo /* hardware does dynamic power save */ 21630686bf7SJohannes Berg if (ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS)) 2175c1b98a5SKalle Valo return TX_CONTINUE; 2185c1b98a5SKalle Valo 2195c1b98a5SKalle Valo /* dynamic power save disabled */ 2205c1b98a5SKalle Valo if (local->hw.conf.dynamic_ps_timeout <= 0) 2215c1b98a5SKalle Valo return TX_CONTINUE; 2225c1b98a5SKalle Valo 2235c1b98a5SKalle Valo /* we are scanning, don't enable power save */ 2245c1b98a5SKalle Valo if (local->scanning) 2255c1b98a5SKalle Valo return TX_CONTINUE; 2265c1b98a5SKalle Valo 2275c1b98a5SKalle Valo if (!local->ps_sdata) 2285c1b98a5SKalle Valo return TX_CONTINUE; 2295c1b98a5SKalle Valo 2305c1b98a5SKalle Valo /* No point if we're going to suspend */ 2315c1b98a5SKalle Valo if (local->quiescing) 2325c1b98a5SKalle Valo return TX_CONTINUE; 2335c1b98a5SKalle Valo 2340c74211dSKalle Valo /* dynamic ps is supported only in managed mode */ 2350c74211dSKalle Valo if (tx->sdata->vif.type != NL80211_IFTYPE_STATION) 2360c74211dSKalle Valo return TX_CONTINUE; 2370c74211dSKalle Valo 23894a5b3acSAndrei Otcheretianski if (unlikely(info->flags & IEEE80211_TX_INTFL_OFFCHAN_TX_OK)) 23994a5b3acSAndrei Otcheretianski return TX_CONTINUE; 24094a5b3acSAndrei Otcheretianski 2410c74211dSKalle Valo ifmgd = &tx->sdata->u.mgd; 2420c74211dSKalle Valo 2430c74211dSKalle Valo /* 2440c74211dSKalle Valo * Don't wakeup from power save if u-apsd is enabled, voip ac has 2450c74211dSKalle Valo * u-apsd enabled and the frame is in voip class. This effectively 2460c74211dSKalle Valo * means that even if all access categories have u-apsd enabled, in 2470c74211dSKalle Valo * practise u-apsd is only used with the voip ac. This is a 2480c74211dSKalle Valo * workaround for the case when received voip class packets do not 2490c74211dSKalle Valo * have correct qos tag for some reason, due the network or the 2500c74211dSKalle Valo * peer application. 2510c74211dSKalle Valo * 252dc41e4d4SEliad Peller * Note: ifmgd->uapsd_queues access is racy here. If the value is 2530c74211dSKalle Valo * changed via debugfs, user needs to reassociate manually to have 2540c74211dSKalle Valo * everything in sync. 2550c74211dSKalle Valo */ 2564875d30dSJohannes Berg if ((ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED) && 2574875d30dSJohannes Berg (ifmgd->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) && 2584875d30dSJohannes Berg skb_get_queue_mapping(tx->skb) == IEEE80211_AC_VO) 2590c74211dSKalle Valo return TX_CONTINUE; 2600c74211dSKalle Valo 2615c1b98a5SKalle Valo if (local->hw.conf.flags & IEEE80211_CONF_PS) { 2625c1b98a5SKalle Valo ieee80211_stop_queues_by_reason(&local->hw, 263445ea4e8SJohannes Berg IEEE80211_MAX_QUEUE_MAP, 264cca07b00SLuciano Coelho IEEE80211_QUEUE_STOP_REASON_PS, 265cca07b00SLuciano Coelho false); 266db28569aSVivek Natarajan ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; 2675c1b98a5SKalle Valo ieee80211_queue_work(&local->hw, 2685c1b98a5SKalle Valo &local->dynamic_ps_disable_work); 2695c1b98a5SKalle Valo } 2705c1b98a5SKalle Valo 2715db1c07cSLuciano Coelho /* Don't restart the timer if we're not disassociated */ 2725db1c07cSLuciano Coelho if (!ifmgd->associated) 2735db1c07cSLuciano Coelho return TX_CONTINUE; 2745db1c07cSLuciano Coelho 2755c1b98a5SKalle Valo mod_timer(&local->dynamic_ps_timer, jiffies + 2765c1b98a5SKalle Valo msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); 2775c1b98a5SKalle Valo 2785c1b98a5SKalle Valo return TX_CONTINUE; 2795c1b98a5SKalle Valo } 280e2ebc74dSJohannes Berg 281d9e8a70fSJohannes Berg static ieee80211_tx_result debug_noinline 2825cf121c3SJohannes Berg ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) 283e2ebc74dSJohannes Berg { 284358c8d9dSHarvey Harrison 285e039fa4aSJohannes Berg struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; 286e039fa4aSJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); 287c2c98fdeSJohannes Berg bool assoc = false; 288e2ebc74dSJohannes Berg 289e039fa4aSJohannes Berg if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) 2909ae54c84SJohannes Berg return TX_CONTINUE; 29158d4185eSJohannes Berg 292b23b025fSBen Greear if (unlikely(test_bit(SCAN_SW_SCANNING, &tx->local->scanning)) && 293b23b025fSBen Greear test_bit(SDATA_STATE_OFFCHANNEL, &tx->sdata->state) && 294a9a6ffffSKalle Valo !ieee80211_is_probe_req(hdr->frame_control) && 29530b2f0beSThomas Pedersen !ieee80211_is_any_nullfunc(hdr->frame_control)) 296a9a6ffffSKalle Valo /* 297a9a6ffffSKalle Valo * When software scanning only nullfunc frames (to notify 298a9a6ffffSKalle Valo * the sleep state to the AP) and probe requests (for the 299a9a6ffffSKalle Valo * active scan) are allowed, all other frames should not be 300a9a6ffffSKalle Valo * sent and we should not get here, but if we do 301a9a6ffffSKalle Valo * nonetheless, drop them to avoid sending them 302a9a6ffffSKalle Valo * off-channel. See the link below and 303a9a6ffffSKalle Valo * ieee80211_start_scan() for more. 304a9a6ffffSKalle Valo * 305a9a6ffffSKalle Valo * http://article.gmane.org/gmane.linux.kernel.wireless.general/30089 306a9a6ffffSKalle Valo */ 3079ae54c84SJohannes Berg return TX_DROP; 308e2ebc74dSJohannes Berg 309239281f8SRostislav Lisovy if (tx->sdata->vif.type == NL80211_IFTYPE_OCB) 310239281f8SRostislav Lisovy return TX_CONTINUE; 311239281f8SRostislav Lisovy 3125cf121c3SJohannes Berg if (tx->flags & IEEE80211_TX_PS_BUFFERED) 3139ae54c84SJohannes Berg return TX_CONTINUE; 314e2ebc74dSJohannes Berg 315c2c98fdeSJohannes Berg if (tx->sta) 316c2c98fdeSJohannes Berg assoc = test_sta_flag(tx->sta, WLAN_STA_ASSOC); 317e2ebc74dSJohannes Berg 3185cf121c3SJohannes Berg if (likely(tx->flags & IEEE80211_TX_UNICAST)) { 319c2c98fdeSJohannes Berg if (unlikely(!assoc && 320358c8d9dSHarvey Harrison ieee80211_is_data(hdr->frame_control))) { 321e2ebc74dSJohannes Berg #ifdef CONFIG_MAC80211_VERBOSE_DEBUG 322bdcbd8e0SJohannes Berg sdata_info(tx->sdata, 323bdcbd8e0SJohannes Berg "dropped data frame to not associated station %pM\n", 324bdcbd8e0SJohannes Berg hdr->addr1); 325bdcbd8e0SJohannes Berg #endif 326e2ebc74dSJohannes Berg I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc); 3279ae54c84SJohannes Berg return TX_DROP; 328e2ebc74dSJohannes Berg } 32972f15d53SMichael Braun } else if (unlikely(ieee80211_is_data(hdr->frame_control) && 33072f15d53SMichael Braun ieee80211_vif_get_num_mcast_if(tx->sdata) == 0)) { 331e2ebc74dSJohannes Berg /* 332e2ebc74dSJohannes Berg * No associated STAs - no need to send multicast 333e2ebc74dSJohannes Berg * frames. 334e2ebc74dSJohannes Berg */ 3359ae54c84SJohannes Berg return TX_DROP; 336e2ebc74dSJohannes Berg } 337e2ebc74dSJohannes Berg 3389ae54c84SJohannes Berg return TX_CONTINUE; 339e2ebc74dSJohannes Berg } 340e2ebc74dSJohannes Berg 341e2ebc74dSJohannes Berg /* This function is called whenever the AP is about to exceed the maximum limit 342e2ebc74dSJohannes Berg * of buffered frames for power saving STAs. This situation should not really 343e2ebc74dSJohannes Berg * happen often during normal operation, so dropping the oldest buffered packet 344e2ebc74dSJohannes Berg * from each queue should be OK to make some room for new frames. */ 345e2ebc74dSJohannes Berg static void purge_old_ps_buffers(struct ieee80211_local *local) 346e2ebc74dSJohannes Berg { 347e2ebc74dSJohannes Berg int total = 0, purged = 0; 348e2ebc74dSJohannes Berg struct sk_buff *skb; 349e2ebc74dSJohannes Berg struct ieee80211_sub_if_data *sdata; 350e2ebc74dSJohannes Berg struct sta_info *sta; 351e2ebc74dSJohannes Berg 35279010420SJohannes Berg list_for_each_entry_rcu(sdata, &local->interfaces, list) { 353d012a605SMarco Porsch struct ps_data *ps; 354d012a605SMarco Porsch 355d012a605SMarco Porsch if (sdata->vif.type == NL80211_IFTYPE_AP) 356d012a605SMarco Porsch ps = &sdata->u.ap.ps; 3573f52b7e3SMarco Porsch else if (ieee80211_vif_is_mesh(&sdata->vif)) 3583f52b7e3SMarco Porsch ps = &sdata->u.mesh.ps; 359d012a605SMarco Porsch else 360e2ebc74dSJohannes Berg continue; 361d012a605SMarco Porsch 362d012a605SMarco Porsch skb = skb_dequeue(&ps->bc_buf); 363e2ebc74dSJohannes Berg if (skb) { 364e2ebc74dSJohannes Berg purged++; 3656b07d9caSFelix Fietkau ieee80211_free_txskb(&local->hw, skb); 366e2ebc74dSJohannes Berg } 367d012a605SMarco Porsch total += skb_queue_len(&ps->bc_buf); 368e2ebc74dSJohannes Berg } 369e2ebc74dSJohannes Berg 370948d887dSJohannes Berg /* 371948d887dSJohannes Berg * Drop one frame from each station from the lowest-priority 372948d887dSJohannes Berg * AC that has frames at all. 373948d887dSJohannes Berg */ 374d0709a65SJohannes Berg list_for_each_entry_rcu(sta, &local->sta_list, list) { 375948d887dSJohannes Berg int ac; 376948d887dSJohannes Berg 377948d887dSJohannes Berg for (ac = IEEE80211_AC_BK; ac >= IEEE80211_AC_VO; ac--) { 378948d887dSJohannes Berg skb = skb_dequeue(&sta->ps_tx_buf[ac]); 379948d887dSJohannes Berg total += skb_queue_len(&sta->ps_tx_buf[ac]); 380e2ebc74dSJohannes Berg if (skb) { 381e2ebc74dSJohannes Berg purged++; 382c3e7724bSFelix Fietkau ieee80211_free_txskb(&local->hw, skb); 383948d887dSJohannes Berg break; 384e2ebc74dSJohannes Berg } 385948d887dSJohannes Berg } 386e2ebc74dSJohannes Berg } 387d0709a65SJohannes Berg 388e2ebc74dSJohannes Berg local->total_ps_buffered = total; 389bdcbd8e0SJohannes Berg ps_dbg_hw(&local->hw, "PS buffers full - purged %d frames\n", purged); 390e2ebc74dSJohannes Berg } 391e2ebc74dSJohannes Berg 3929ae54c84SJohannes Berg static ieee80211_tx_result 3935cf121c3SJohannes Berg ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) 394e2ebc74dSJohannes Berg { 395e039fa4aSJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); 396358c8d9dSHarvey Harrison struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; 397d012a605SMarco Porsch struct ps_data *ps; 398e039fa4aSJohannes Berg 3997d54d0ddSJohannes Berg /* 4007d54d0ddSJohannes Berg * broadcast/multicast frame 4017d54d0ddSJohannes Berg * 4023f52b7e3SMarco Porsch * If any of the associated/peer stations is in power save mode, 4037d54d0ddSJohannes Berg * the frame is buffered to be sent after DTIM beacon frame. 4047d54d0ddSJohannes Berg * This is done either by the hardware or us. 4057d54d0ddSJohannes Berg */ 4067d54d0ddSJohannes Berg 4073f52b7e3SMarco Porsch /* powersaving STAs currently only in AP/VLAN/mesh mode */ 408d012a605SMarco Porsch if (tx->sdata->vif.type == NL80211_IFTYPE_AP || 409d012a605SMarco Porsch tx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { 4103e122be0SJohannes Berg if (!tx->sdata->bss) 4113e122be0SJohannes Berg return TX_CONTINUE; 4123e122be0SJohannes Berg 413d012a605SMarco Porsch ps = &tx->sdata->bss->ps; 4143f52b7e3SMarco Porsch } else if (ieee80211_vif_is_mesh(&tx->sdata->vif)) { 4153f52b7e3SMarco Porsch ps = &tx->sdata->u.mesh.ps; 416d012a605SMarco Porsch } else { 417d012a605SMarco Porsch return TX_CONTINUE; 418d012a605SMarco Porsch } 419d012a605SMarco Porsch 420d012a605SMarco Porsch 4213e122be0SJohannes Berg /* no buffering for ordered frames */ 422358c8d9dSHarvey Harrison if (ieee80211_has_order(hdr->frame_control)) 4239ae54c84SJohannes Berg return TX_CONTINUE; 4247d54d0ddSJohannes Berg 42508b99399SJohannes Berg if (ieee80211_is_probe_req(hdr->frame_control)) 42608b99399SJohannes Berg return TX_CONTINUE; 42708b99399SJohannes Berg 42830686bf7SJohannes Berg if (ieee80211_hw_check(&tx->local->hw, QUEUE_CONTROL)) 429f4d57941SJohannes Berg info->hw_queue = tx->sdata->vif.cab_queue; 430f4d57941SJohannes Berg 4319ec1190dSFelix Fietkau /* no stations in PS mode and no buffered packets */ 4329ec1190dSFelix Fietkau if (!atomic_read(&ps->num_sta_ps) && skb_queue_empty(&ps->bc_buf)) 4339ae54c84SJohannes Berg return TX_CONTINUE; 4347d54d0ddSJohannes Berg 43562b1208eSJohannes Berg info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM; 43662b1208eSJohannes Berg 43762b517cbSJohannes Berg /* device releases frame after DTIM beacon */ 43830686bf7SJohannes Berg if (!ieee80211_hw_check(&tx->local->hw, HOST_BROADCAST_PS_BUFFERING)) 43962b1208eSJohannes Berg return TX_CONTINUE; 44062b1208eSJohannes Berg 4417d54d0ddSJohannes Berg /* buffered in mac80211 */ 442e2ebc74dSJohannes Berg if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) 443e2ebc74dSJohannes Berg purge_old_ps_buffers(tx->local); 44462b1208eSJohannes Berg 445d012a605SMarco Porsch if (skb_queue_len(&ps->bc_buf) >= AP_MAX_BC_BUFFER) { 446bdcbd8e0SJohannes Berg ps_dbg(tx->sdata, 447bdcbd8e0SJohannes Berg "BC TX buffer full - dropping the oldest frame\n"); 4486b07d9caSFelix Fietkau ieee80211_free_txskb(&tx->local->hw, skb_dequeue(&ps->bc_buf)); 449e2ebc74dSJohannes Berg } else 450e2ebc74dSJohannes Berg tx->local->total_ps_buffered++; 45162b1208eSJohannes Berg 452d012a605SMarco Porsch skb_queue_tail(&ps->bc_buf, tx->skb); 45362b1208eSJohannes Berg 4549ae54c84SJohannes Berg return TX_QUEUED; 455e2ebc74dSJohannes Berg } 456e2ebc74dSJohannes Berg 457fb733336SJouni Malinen static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta, 458fb733336SJouni Malinen struct sk_buff *skb) 459fb733336SJouni Malinen { 460fb733336SJouni Malinen if (!ieee80211_is_mgmt(fc)) 461fb733336SJouni Malinen return 0; 462fb733336SJouni Malinen 463c2c98fdeSJohannes Berg if (sta == NULL || !test_sta_flag(sta, WLAN_STA_MFP)) 464fb733336SJouni Malinen return 0; 465fb733336SJouni Malinen 466d8ca16dbSJohannes Berg if (!ieee80211_is_robust_mgmt_frame(skb)) 467fb733336SJouni Malinen return 0; 468fb733336SJouni Malinen 469fb733336SJouni Malinen return 1; 470fb733336SJouni Malinen } 471fb733336SJouni Malinen 4729ae54c84SJohannes Berg static ieee80211_tx_result 4735cf121c3SJohannes Berg ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) 474e2ebc74dSJohannes Berg { 475e2ebc74dSJohannes Berg struct sta_info *sta = tx->sta; 476e039fa4aSJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); 47708b99399SJohannes Berg struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; 4783393a608SJuuso Oikarinen struct ieee80211_local *local = tx->local; 479e2ebc74dSJohannes Berg 48002f2f1a9SJohannes Berg if (unlikely(!sta)) 4819ae54c84SJohannes Berg return TX_CONTINUE; 482e2ebc74dSJohannes Berg 483c2c98fdeSJohannes Berg if (unlikely((test_sta_flag(sta, WLAN_STA_PS_STA) || 4845ac2e350SJohannes Berg test_sta_flag(sta, WLAN_STA_PS_DRIVER) || 4855ac2e350SJohannes Berg test_sta_flag(sta, WLAN_STA_PS_DELIVER)) && 48602f2f1a9SJohannes Berg !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) { 487948d887dSJohannes Berg int ac = skb_get_queue_mapping(tx->skb); 488948d887dSJohannes Berg 48908b99399SJohannes Berg if (ieee80211_is_mgmt(hdr->frame_control) && 49008b99399SJohannes Berg !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) { 49108b99399SJohannes Berg info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; 49208b99399SJohannes Berg return TX_CONTINUE; 49308b99399SJohannes Berg } 49408b99399SJohannes Berg 495bdcbd8e0SJohannes Berg ps_dbg(sta->sdata, "STA %pM aid %d: PS buffer for AC %d\n", 496948d887dSJohannes Berg sta->sta.addr, sta->sta.aid, ac); 497e2ebc74dSJohannes Berg if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) 498e2ebc74dSJohannes Berg purge_old_ps_buffers(tx->local); 4991d147bfaSEmmanuel Grumbach 5001d147bfaSEmmanuel Grumbach /* sync with ieee80211_sta_ps_deliver_wakeup */ 5011d147bfaSEmmanuel Grumbach spin_lock(&sta->ps_lock); 5021d147bfaSEmmanuel Grumbach /* 5031d147bfaSEmmanuel Grumbach * STA woke up the meantime and all the frames on ps_tx_buf have 5041d147bfaSEmmanuel Grumbach * been queued to pending queue. No reordering can happen, go 5051d147bfaSEmmanuel Grumbach * ahead and Tx the packet. 5061d147bfaSEmmanuel Grumbach */ 5071d147bfaSEmmanuel Grumbach if (!test_sta_flag(sta, WLAN_STA_PS_STA) && 5085ac2e350SJohannes Berg !test_sta_flag(sta, WLAN_STA_PS_DRIVER) && 5095ac2e350SJohannes Berg !test_sta_flag(sta, WLAN_STA_PS_DELIVER)) { 5101d147bfaSEmmanuel Grumbach spin_unlock(&sta->ps_lock); 5111d147bfaSEmmanuel Grumbach return TX_CONTINUE; 5121d147bfaSEmmanuel Grumbach } 5131d147bfaSEmmanuel Grumbach 514948d887dSJohannes Berg if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) { 515948d887dSJohannes Berg struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]); 516bdcbd8e0SJohannes Berg ps_dbg(tx->sdata, 517bdcbd8e0SJohannes Berg "STA %pM TX buffer for AC %d full - dropping oldest frame\n", 518bdcbd8e0SJohannes Berg sta->sta.addr, ac); 519c3e7724bSFelix Fietkau ieee80211_free_txskb(&local->hw, old); 520e2ebc74dSJohannes Berg } else 521e2ebc74dSJohannes Berg tx->local->total_ps_buffered++; 522004c872eSJohannes Berg 523e039fa4aSJohannes Berg info->control.jiffies = jiffies; 5245061b0c2SJohannes Berg info->control.vif = &tx->sdata->vif; 525cc20ff2cSFelix Fietkau info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING; 52603c8c06fSJohannes Berg info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS; 527948d887dSJohannes Berg skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb); 5281d147bfaSEmmanuel Grumbach spin_unlock(&sta->ps_lock); 5293393a608SJuuso Oikarinen 5303393a608SJuuso Oikarinen if (!timer_pending(&local->sta_cleanup)) 5313393a608SJuuso Oikarinen mod_timer(&local->sta_cleanup, 5323393a608SJuuso Oikarinen round_jiffies(jiffies + 5333393a608SJuuso Oikarinen STA_INFO_CLEANUP_INTERVAL)); 5343393a608SJuuso Oikarinen 535c868cb35SJohannes Berg /* 536c868cb35SJohannes Berg * We queued up some frames, so the TIM bit might 537c868cb35SJohannes Berg * need to be set, recalculate it. 538c868cb35SJohannes Berg */ 539c868cb35SJohannes Berg sta_info_recalc_tim(sta); 540c868cb35SJohannes Berg 5419ae54c84SJohannes Berg return TX_QUEUED; 542bdcbd8e0SJohannes Berg } else if (unlikely(test_sta_flag(sta, WLAN_STA_PS_STA))) { 543bdcbd8e0SJohannes Berg ps_dbg(tx->sdata, 544bdcbd8e0SJohannes Berg "STA %pM in PS mode, but polling/in SP -> send frame\n", 545bdcbd8e0SJohannes Berg sta->sta.addr); 546e2ebc74dSJohannes Berg } 547e2ebc74dSJohannes Berg 5489ae54c84SJohannes Berg return TX_CONTINUE; 549e2ebc74dSJohannes Berg } 550e2ebc74dSJohannes Berg 551d9e8a70fSJohannes Berg static ieee80211_tx_result debug_noinline 5525cf121c3SJohannes Berg ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx) 553e2ebc74dSJohannes Berg { 5545cf121c3SJohannes Berg if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED)) 5559ae54c84SJohannes Berg return TX_CONTINUE; 556e2ebc74dSJohannes Berg 5575cf121c3SJohannes Berg if (tx->flags & IEEE80211_TX_UNICAST) 558e2ebc74dSJohannes Berg return ieee80211_tx_h_unicast_ps_buf(tx); 559e2ebc74dSJohannes Berg else 560e2ebc74dSJohannes Berg return ieee80211_tx_h_multicast_ps_buf(tx); 561e2ebc74dSJohannes Berg } 562e2ebc74dSJohannes Berg 563d9e8a70fSJohannes Berg static ieee80211_tx_result debug_noinline 564a621fa4dSJohannes Berg ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data *tx) 565a621fa4dSJohannes Berg { 566a621fa4dSJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); 567a621fa4dSJohannes Berg 568af61a165SJohannes Berg if (unlikely(tx->sdata->control_port_protocol == tx->skb->protocol)) { 569af61a165SJohannes Berg if (tx->sdata->control_port_no_encrypt) 570a621fa4dSJohannes Berg info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; 571af61a165SJohannes Berg info->control.flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO; 5729c1c98a3SJouni Malinen info->flags |= IEEE80211_TX_CTL_USE_MINRATE; 573af61a165SJohannes Berg } 574a621fa4dSJohannes Berg 575a621fa4dSJohannes Berg return TX_CONTINUE; 576a621fa4dSJohannes Berg } 577a621fa4dSJohannes Berg 578a621fa4dSJohannes Berg static ieee80211_tx_result debug_noinline 5795cf121c3SJohannes Berg ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) 580e2ebc74dSJohannes Berg { 58146e6de15SJohannes Berg struct ieee80211_key *key; 582e039fa4aSJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); 583358c8d9dSHarvey Harrison struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; 584d4e46a3dSJohannes Berg 585a0761a30SJohannes Berg if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) { 586e2ebc74dSJohannes Berg tx->key = NULL; 587a0761a30SJohannes Berg return TX_CONTINUE; 588a0761a30SJohannes Berg } 589a0761a30SJohannes Berg 590a0761a30SJohannes Berg if (tx->sta && 5912475b1ccSMax Stepanov (key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx]))) 592d4e46a3dSJohannes Berg tx->key = key; 59346f6b060SMasashi Honma else if (ieee80211_is_group_privacy_action(tx->skb) && 59446f6b060SMasashi Honma (key = rcu_dereference(tx->sdata->default_multicast_key))) 59546f6b060SMasashi Honma tx->key = key; 5963cfcf6acSJouni Malinen else if (ieee80211_is_mgmt(hdr->frame_control) && 597ecbcd324SJouni Malinen is_multicast_ether_addr(hdr->addr1) && 598d8ca16dbSJohannes Berg ieee80211_is_robust_mgmt_frame(tx->skb) && 5993cfcf6acSJouni Malinen (key = rcu_dereference(tx->sdata->default_mgmt_key))) 6003cfcf6acSJouni Malinen tx->key = key; 601f7e0104cSJohannes Berg else if (is_multicast_ether_addr(hdr->addr1) && 602f7e0104cSJohannes Berg (key = rcu_dereference(tx->sdata->default_multicast_key))) 603f7e0104cSJohannes Berg tx->key = key; 604f7e0104cSJohannes Berg else if (!is_multicast_ether_addr(hdr->addr1) && 605f7e0104cSJohannes Berg (key = rcu_dereference(tx->sdata->default_unicast_key))) 606d4e46a3dSJohannes Berg tx->key = key; 607e8f4fb7cSJohannes Berg else 60846e6de15SJohannes Berg tx->key = NULL; 609e2ebc74dSJohannes Berg 610e2ebc74dSJohannes Berg if (tx->key) { 611813d7669SJohannes Berg bool skip_hw = false; 612813d7669SJohannes Berg 613011bfcc4SJohannes Berg /* TODO: add threshold stuff again */ 614176e4f84SJohannes Berg 61597359d12SJohannes Berg switch (tx->key->conf.cipher) { 61697359d12SJohannes Berg case WLAN_CIPHER_SUITE_WEP40: 61797359d12SJohannes Berg case WLAN_CIPHER_SUITE_WEP104: 61897359d12SJohannes Berg case WLAN_CIPHER_SUITE_TKIP: 619358c8d9dSHarvey Harrison if (!ieee80211_is_data_present(hdr->frame_control)) 620176e4f84SJohannes Berg tx->key = NULL; 621176e4f84SJohannes Berg break; 62297359d12SJohannes Berg case WLAN_CIPHER_SUITE_CCMP: 6232b2ba0dbSJouni Malinen case WLAN_CIPHER_SUITE_CCMP_256: 62400b9cfa3SJouni Malinen case WLAN_CIPHER_SUITE_GCMP: 62500b9cfa3SJouni Malinen case WLAN_CIPHER_SUITE_GCMP_256: 626fb733336SJouni Malinen if (!ieee80211_is_data_present(hdr->frame_control) && 627fb733336SJouni Malinen !ieee80211_use_mfp(hdr->frame_control, tx->sta, 62846f6b060SMasashi Honma tx->skb) && 62946f6b060SMasashi Honma !ieee80211_is_group_privacy_action(tx->skb)) 630fb733336SJouni Malinen tx->key = NULL; 6313b43a187SKalle Valo else 632813d7669SJohannes Berg skip_hw = (tx->key->conf.flags & 633e548c49eSJohannes Berg IEEE80211_KEY_FLAG_SW_MGMT_TX) && 634813d7669SJohannes Berg ieee80211_is_mgmt(hdr->frame_control); 635fb733336SJouni Malinen break; 63697359d12SJohannes Berg case WLAN_CIPHER_SUITE_AES_CMAC: 63756c52da2SJouni Malinen case WLAN_CIPHER_SUITE_BIP_CMAC_256: 6388ade538bSJouni Malinen case WLAN_CIPHER_SUITE_BIP_GMAC_128: 6398ade538bSJouni Malinen case WLAN_CIPHER_SUITE_BIP_GMAC_256: 6403cfcf6acSJouni Malinen if (!ieee80211_is_mgmt(hdr->frame_control)) 6413cfcf6acSJouni Malinen tx->key = NULL; 6423cfcf6acSJouni Malinen break; 643e2ebc74dSJohannes Berg } 644813d7669SJohannes Berg 645e54faf29SJohannes Berg if (unlikely(tx->key && tx->key->flags & KEY_FLAG_TAINTED && 646e54faf29SJohannes Berg !ieee80211_is_deauth(hdr->frame_control))) 64795acac61SJohannes Berg return TX_DROP; 64895acac61SJohannes Berg 649f12553ebSJohannes Berg if (!skip_hw && tx->key && 650382b1655SJohannes Berg tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) 651813d7669SJohannes Berg info->control.hw_key = &tx->key->conf; 6522463ec86SFelix Fietkau } else if (ieee80211_is_data_present(hdr->frame_control) && tx->sta && 653a0761a30SJohannes Berg test_sta_flag(tx->sta, WLAN_STA_USES_ENCRYPTION)) { 654a0761a30SJohannes Berg return TX_DROP; 655176e4f84SJohannes Berg } 656176e4f84SJohannes Berg 6579ae54c84SJohannes Berg return TX_CONTINUE; 658e2ebc74dSJohannes Berg } 659e2ebc74dSJohannes Berg 660d9e8a70fSJohannes Berg static ieee80211_tx_result debug_noinline 6615cf121c3SJohannes Berg ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) 662e2ebc74dSJohannes Berg { 663e039fa4aSJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); 664e6a9854bSJohannes Berg struct ieee80211_hdr *hdr = (void *)tx->skb->data; 665e6a9854bSJohannes Berg struct ieee80211_supported_band *sband; 666a2c40249SShanyu Zhao u32 len; 667e6a9854bSJohannes Berg struct ieee80211_tx_rate_control txrc; 6680d528d85SFelix Fietkau struct ieee80211_sta_rates *ratetbl = NULL; 669c2c98fdeSJohannes Berg bool assoc = false; 670e6a9854bSJohannes Berg 671e6a9854bSJohannes Berg memset(&txrc, 0, sizeof(txrc)); 6728318d78aSJohannes Berg 6732d56577bSJohannes Berg sband = tx->local->hw.wiphy->bands[info->band]; 674e2ebc74dSJohannes Berg 675a2c40249SShanyu Zhao len = min_t(u32, tx->skb->len + FCS_LEN, 676b9a5f8caSJouni Malinen tx->local->hw.wiphy->frag_threshold); 67758d4185eSJohannes Berg 678e6a9854bSJohannes Berg /* set up the tx rate control struct we give the RC algo */ 679005e472bSJohannes Berg txrc.hw = &tx->local->hw; 680e6a9854bSJohannes Berg txrc.sband = sband; 681e6a9854bSJohannes Berg txrc.bss_conf = &tx->sdata->vif.bss_conf; 682e6a9854bSJohannes Berg txrc.skb = tx->skb; 683e6a9854bSJohannes Berg txrc.reported_rate.idx = -1; 6842d56577bSJohannes Berg txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[info->band]; 6852ffbe6d3SFelix Fietkau 6862ffbe6d3SFelix Fietkau if (tx->sdata->rc_has_mcs_mask[info->band]) 6872ffbe6d3SFelix Fietkau txrc.rate_idx_mcs_mask = 6882ffbe6d3SFelix Fietkau tx->sdata->rc_rateidx_mcs_mask[info->band]; 6892ffbe6d3SFelix Fietkau 6908f0729b1SFelix Fietkau txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP || 6914bb62344SChun-Yeow Yeoh tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT || 6925765f9f6SBertold Van den Bergh tx->sdata->vif.type == NL80211_IFTYPE_ADHOC || 6935765f9f6SBertold Van den Bergh tx->sdata->vif.type == NL80211_IFTYPE_OCB); 69458d4185eSJohannes Berg 695e6a9854bSJohannes Berg /* set up RTS protection if desired */ 696b9a5f8caSJouni Malinen if (len > tx->local->hw.wiphy->rts_threshold) { 6970d528d85SFelix Fietkau txrc.rts = true; 698e2ebc74dSJohannes Berg } 699e6a9854bSJohannes Berg 7000d528d85SFelix Fietkau info->control.use_rts = txrc.rts; 701991fec09SFelix Fietkau info->control.use_cts_prot = tx->sdata->vif.bss_conf.use_cts_prot; 702991fec09SFelix Fietkau 703e6a9854bSJohannes Berg /* 704e6a9854bSJohannes Berg * Use short preamble if the BSS can handle it, but not for 705e6a9854bSJohannes Berg * management frames unless we know the receiver can handle 706e6a9854bSJohannes Berg * that -- the management frame might be to a station that 707e6a9854bSJohannes Berg * just wants a probe response. 708e6a9854bSJohannes Berg */ 709e6a9854bSJohannes Berg if (tx->sdata->vif.bss_conf.use_short_preamble && 710e6a9854bSJohannes Berg (ieee80211_is_data(hdr->frame_control) || 711c2c98fdeSJohannes Berg (tx->sta && test_sta_flag(tx->sta, WLAN_STA_SHORT_PREAMBLE)))) 7120d528d85SFelix Fietkau txrc.short_preamble = true; 7130d528d85SFelix Fietkau 7140d528d85SFelix Fietkau info->control.short_preamble = txrc.short_preamble; 715e6a9854bSJohannes Berg 716dfdfc2beSSven Eckelmann /* don't ask rate control when rate already injected via radiotap */ 717dfdfc2beSSven Eckelmann if (info->control.flags & IEEE80211_TX_CTRL_RATE_INJECT) 718dfdfc2beSSven Eckelmann return TX_CONTINUE; 719dfdfc2beSSven Eckelmann 720c2c98fdeSJohannes Berg if (tx->sta) 721c2c98fdeSJohannes Berg assoc = test_sta_flag(tx->sta, WLAN_STA_ASSOC); 722e6a9854bSJohannes Berg 723b770b43eSLuis R. Rodriguez /* 724b770b43eSLuis R. Rodriguez * Lets not bother rate control if we're associated and cannot 725b770b43eSLuis R. Rodriguez * talk to the sta. This should not happen. 726b770b43eSLuis R. Rodriguez */ 727c2c98fdeSJohannes Berg if (WARN(test_bit(SCAN_SW_SCANNING, &tx->local->scanning) && assoc && 728b770b43eSLuis R. Rodriguez !rate_usable_index_exists(sband, &tx->sta->sta), 729b770b43eSLuis R. Rodriguez "%s: Dropped data frame as no usable bitrate found while " 730b770b43eSLuis R. Rodriguez "scanning and associated. Target station: " 731b770b43eSLuis R. Rodriguez "%pM on %d GHz band\n", 73247846c9bSJohannes Berg tx->sdata->name, hdr->addr1, 7332d56577bSJohannes Berg info->band ? 5 : 2)) 734b770b43eSLuis R. Rodriguez return TX_DROP; 735b770b43eSLuis R. Rodriguez 736b770b43eSLuis R. Rodriguez /* 737b770b43eSLuis R. Rodriguez * If we're associated with the sta at this point we know we can at 738b770b43eSLuis R. Rodriguez * least send the frame at the lowest bit rate. 739b770b43eSLuis R. Rodriguez */ 740e6a9854bSJohannes Berg rate_control_get_rate(tx->sdata, tx->sta, &txrc); 741e6a9854bSJohannes Berg 7420d528d85SFelix Fietkau if (tx->sta && !info->control.skip_table) 7430d528d85SFelix Fietkau ratetbl = rcu_dereference(tx->sta->sta.rates); 7440d528d85SFelix Fietkau 7450d528d85SFelix Fietkau if (unlikely(info->control.rates[0].idx < 0)) { 7460d528d85SFelix Fietkau if (ratetbl) { 7470d528d85SFelix Fietkau struct ieee80211_tx_rate rate = { 7480d528d85SFelix Fietkau .idx = ratetbl->rate[0].idx, 7490d528d85SFelix Fietkau .flags = ratetbl->rate[0].flags, 7500d528d85SFelix Fietkau .count = ratetbl->rate[0].count 7510d528d85SFelix Fietkau }; 7520d528d85SFelix Fietkau 7530d528d85SFelix Fietkau if (ratetbl->rate[0].idx < 0) 754e6a9854bSJohannes Berg return TX_DROP; 755e6a9854bSJohannes Berg 7560d528d85SFelix Fietkau tx->rate = rate; 7570d528d85SFelix Fietkau } else { 7580d528d85SFelix Fietkau return TX_DROP; 7590d528d85SFelix Fietkau } 7600d528d85SFelix Fietkau } else { 7610d528d85SFelix Fietkau tx->rate = info->control.rates[0]; 7620d528d85SFelix Fietkau } 7630d528d85SFelix Fietkau 764c1ce5a74SHelmut Schaa if (txrc.reported_rate.idx < 0) { 7650d528d85SFelix Fietkau txrc.reported_rate = tx->rate; 766c1ce5a74SHelmut Schaa if (tx->sta && ieee80211_is_data(hdr->frame_control)) 767e5a9f8d0SJohannes Berg tx->sta->tx_stats.last_rate = txrc.reported_rate; 768c1ce5a74SHelmut Schaa } else if (tx->sta) 769e5a9f8d0SJohannes Berg tx->sta->tx_stats.last_rate = txrc.reported_rate; 770e6a9854bSJohannes Berg 7710d528d85SFelix Fietkau if (ratetbl) 7720d528d85SFelix Fietkau return TX_CONTINUE; 7730d528d85SFelix Fietkau 774e6a9854bSJohannes Berg if (unlikely(!info->control.rates[0].count)) 775e6a9854bSJohannes Berg info->control.rates[0].count = 1; 776e6a9854bSJohannes Berg 7779955151dSGábor Stefanik if (WARN_ON_ONCE((info->control.rates[0].count > 1) && 7789955151dSGábor Stefanik (info->flags & IEEE80211_TX_CTL_NO_ACK))) 7799955151dSGábor Stefanik info->control.rates[0].count = 1; 7809955151dSGábor Stefanik 7819ae54c84SJohannes Berg return TX_CONTINUE; 782e2ebc74dSJohannes Berg } 783e2ebc74dSJohannes Berg 784ba8c3d6fSFelix Fietkau static __le16 ieee80211_tx_next_seq(struct sta_info *sta, int tid) 785ba8c3d6fSFelix Fietkau { 786ba8c3d6fSFelix Fietkau u16 *seq = &sta->tid_seq[tid]; 787ba8c3d6fSFelix Fietkau __le16 ret = cpu_to_le16(*seq); 788ba8c3d6fSFelix Fietkau 789ba8c3d6fSFelix Fietkau /* Increase the sequence number. */ 790ba8c3d6fSFelix Fietkau *seq = (*seq + 0x10) & IEEE80211_SCTL_SEQ; 791ba8c3d6fSFelix Fietkau 792ba8c3d6fSFelix Fietkau return ret; 793ba8c3d6fSFelix Fietkau } 794ba8c3d6fSFelix Fietkau 795d9e8a70fSJohannes Berg static ieee80211_tx_result debug_noinline 796f591fa5dSJohannes Berg ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) 797f591fa5dSJohannes Berg { 798f591fa5dSJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); 799f591fa5dSJohannes Berg struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; 800f591fa5dSJohannes Berg int tid; 801f591fa5dSJohannes Berg 80225d834e1SJohannes Berg /* 80325d834e1SJohannes Berg * Packet injection may want to control the sequence 80425d834e1SJohannes Berg * number, if we have no matching interface then we 80525d834e1SJohannes Berg * neither assign one ourselves nor ask the driver to. 80625d834e1SJohannes Berg */ 8075061b0c2SJohannes Berg if (unlikely(info->control.vif->type == NL80211_IFTYPE_MONITOR)) 80825d834e1SJohannes Berg return TX_CONTINUE; 80925d834e1SJohannes Berg 810f591fa5dSJohannes Berg if (unlikely(ieee80211_is_ctl(hdr->frame_control))) 811f591fa5dSJohannes Berg return TX_CONTINUE; 812f591fa5dSJohannes Berg 813f591fa5dSJohannes Berg if (ieee80211_hdrlen(hdr->frame_control) < 24) 814f591fa5dSJohannes Berg return TX_CONTINUE; 815f591fa5dSJohannes Berg 81649a59543SJohannes Berg if (ieee80211_is_qos_nullfunc(hdr->frame_control)) 81749a59543SJohannes Berg return TX_CONTINUE; 81849a59543SJohannes Berg 81929c3e95fSMathy Vanhoef if (info->control.flags & IEEE80211_TX_CTRL_NO_SEQNO) 82029c3e95fSMathy Vanhoef return TX_CONTINUE; 82129c3e95fSMathy Vanhoef 82294778280SJohannes Berg /* 82394778280SJohannes Berg * Anything but QoS data that has a sequence number field 82494778280SJohannes Berg * (is long enough) gets a sequence number from the global 825c4c205f3SBob Copeland * counter. QoS data frames with a multicast destination 826c4c205f3SBob Copeland * also use the global counter (802.11-2012 9.3.2.10). 82794778280SJohannes Berg */ 828c4c205f3SBob Copeland if (!ieee80211_is_data_qos(hdr->frame_control) || 829c4c205f3SBob Copeland is_multicast_ether_addr(hdr->addr1)) { 83094778280SJohannes Berg /* driver should assign sequence number */ 831f591fa5dSJohannes Berg info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; 83294778280SJohannes Berg /* for pure STA mode without beacons, we can do it */ 83394778280SJohannes Berg hdr->seq_ctrl = cpu_to_le16(tx->sdata->sequence_number); 83494778280SJohannes Berg tx->sdata->sequence_number += 0x10; 83579c892b8SJohannes Berg if (tx->sta) 836e5a9f8d0SJohannes Berg tx->sta->tx_stats.msdu[IEEE80211_NUM_TIDS]++; 837f591fa5dSJohannes Berg return TX_CONTINUE; 838f591fa5dSJohannes Berg } 839f591fa5dSJohannes Berg 840f591fa5dSJohannes Berg /* 841f591fa5dSJohannes Berg * This should be true for injected/management frames only, for 842f591fa5dSJohannes Berg * management frames we have set the IEEE80211_TX_CTL_ASSIGN_SEQ 843f591fa5dSJohannes Berg * above since they are not QoS-data frames. 844f591fa5dSJohannes Berg */ 845f591fa5dSJohannes Berg if (!tx->sta) 846f591fa5dSJohannes Berg return TX_CONTINUE; 847f591fa5dSJohannes Berg 848f591fa5dSJohannes Berg /* include per-STA, per-TID sequence counter */ 849a1f2ba04SSara Sharon tid = ieee80211_get_tid(hdr); 850e5a9f8d0SJohannes Berg tx->sta->tx_stats.msdu[tid]++; 851f591fa5dSJohannes Berg 852ba8c3d6fSFelix Fietkau hdr->seq_ctrl = ieee80211_tx_next_seq(tx->sta, tid); 853f591fa5dSJohannes Berg 854f591fa5dSJohannes Berg return TX_CONTINUE; 855f591fa5dSJohannes Berg } 856f591fa5dSJohannes Berg 857252b86c4SJohannes Berg static int ieee80211_fragment(struct ieee80211_tx_data *tx, 8582de8e0d9SJohannes Berg struct sk_buff *skb, int hdrlen, 8592de8e0d9SJohannes Berg int frag_threshold) 8602de8e0d9SJohannes Berg { 861252b86c4SJohannes Berg struct ieee80211_local *local = tx->local; 862a1a3fcecSJohannes Berg struct ieee80211_tx_info *info; 863252b86c4SJohannes Berg struct sk_buff *tmp; 8642de8e0d9SJohannes Berg int per_fragm = frag_threshold - hdrlen - FCS_LEN; 8652de8e0d9SJohannes Berg int pos = hdrlen + per_fragm; 8662de8e0d9SJohannes Berg int rem = skb->len - hdrlen - per_fragm; 8672de8e0d9SJohannes Berg 8682de8e0d9SJohannes Berg if (WARN_ON(rem < 0)) 8692de8e0d9SJohannes Berg return -EINVAL; 8702de8e0d9SJohannes Berg 871252b86c4SJohannes Berg /* first fragment was already added to queue by caller */ 872252b86c4SJohannes Berg 8732de8e0d9SJohannes Berg while (rem) { 8742de8e0d9SJohannes Berg int fraglen = per_fragm; 8752de8e0d9SJohannes Berg 8762de8e0d9SJohannes Berg if (fraglen > rem) 8772de8e0d9SJohannes Berg fraglen = rem; 8782de8e0d9SJohannes Berg rem -= fraglen; 8792de8e0d9SJohannes Berg tmp = dev_alloc_skb(local->tx_headroom + 8802de8e0d9SJohannes Berg frag_threshold + 8812475b1ccSMax Stepanov tx->sdata->encrypt_headroom + 8822de8e0d9SJohannes Berg IEEE80211_ENCRYPT_TAILROOM); 8832de8e0d9SJohannes Berg if (!tmp) 8842de8e0d9SJohannes Berg return -ENOMEM; 885252b86c4SJohannes Berg 886252b86c4SJohannes Berg __skb_queue_tail(&tx->skbs, tmp); 887252b86c4SJohannes Berg 8882475b1ccSMax Stepanov skb_reserve(tmp, 8892475b1ccSMax Stepanov local->tx_headroom + tx->sdata->encrypt_headroom); 8902475b1ccSMax Stepanov 8912de8e0d9SJohannes Berg /* copy control information */ 8922de8e0d9SJohannes Berg memcpy(tmp->cb, skb->cb, sizeof(tmp->cb)); 893a1a3fcecSJohannes Berg 894a1a3fcecSJohannes Berg info = IEEE80211_SKB_CB(tmp); 895a1a3fcecSJohannes Berg info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT | 896a1a3fcecSJohannes Berg IEEE80211_TX_CTL_FIRST_FRAGMENT); 897a1a3fcecSJohannes Berg 898a1a3fcecSJohannes Berg if (rem) 899a1a3fcecSJohannes Berg info->flags |= IEEE80211_TX_CTL_MORE_FRAMES; 900a1a3fcecSJohannes Berg 9012de8e0d9SJohannes Berg skb_copy_queue_mapping(tmp, skb); 9022de8e0d9SJohannes Berg tmp->priority = skb->priority; 9032de8e0d9SJohannes Berg tmp->dev = skb->dev; 9042de8e0d9SJohannes Berg 9052de8e0d9SJohannes Berg /* copy header and data */ 90659ae1d12SJohannes Berg skb_put_data(tmp, skb->data, hdrlen); 90759ae1d12SJohannes Berg skb_put_data(tmp, skb->data + pos, fraglen); 9082de8e0d9SJohannes Berg 9092de8e0d9SJohannes Berg pos += fraglen; 9102de8e0d9SJohannes Berg } 9112de8e0d9SJohannes Berg 912252b86c4SJohannes Berg /* adjust first fragment's length */ 913338f977fSJohannes Berg skb_trim(skb, hdrlen + per_fragm); 9142de8e0d9SJohannes Berg return 0; 9152de8e0d9SJohannes Berg } 9162de8e0d9SJohannes Berg 917f591fa5dSJohannes Berg static ieee80211_tx_result debug_noinline 918e2454948SJohannes Berg ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) 919e2454948SJohannes Berg { 9202de8e0d9SJohannes Berg struct sk_buff *skb = tx->skb; 9212de8e0d9SJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 9222de8e0d9SJohannes Berg struct ieee80211_hdr *hdr = (void *)skb->data; 923b9a5f8caSJouni Malinen int frag_threshold = tx->local->hw.wiphy->frag_threshold; 9242de8e0d9SJohannes Berg int hdrlen; 9252de8e0d9SJohannes Berg int fragnum; 926e2454948SJohannes Berg 927252b86c4SJohannes Berg /* no matter what happens, tx->skb moves to tx->skbs */ 928252b86c4SJohannes Berg __skb_queue_tail(&tx->skbs, skb); 929252b86c4SJohannes Berg tx->skb = NULL; 930252b86c4SJohannes Berg 931a26eb27aSJohannes Berg if (info->flags & IEEE80211_TX_CTL_DONTFRAG) 932a26eb27aSJohannes Berg return TX_CONTINUE; 933a26eb27aSJohannes Berg 934f3fe4e93SSara Sharon if (ieee80211_hw_check(&tx->local->hw, SUPPORTS_TX_FRAG)) 935e2454948SJohannes Berg return TX_CONTINUE; 936e2454948SJohannes Berg 937eefce91aSJohannes Berg /* 938eefce91aSJohannes Berg * Warn when submitting a fragmented A-MPDU frame and drop it. 9393b8d81e0SJohannes Berg * This scenario is handled in ieee80211_tx_prepare but extra 9408d5e0d58SRon Rindjunsky * caution taken here as fragmented ampdu may cause Tx stop. 941eefce91aSJohannes Berg */ 9428b30b1feSSujith if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU)) 943eefce91aSJohannes Berg return TX_DROP; 944eefce91aSJohannes Berg 945065e9605SHarvey Harrison hdrlen = ieee80211_hdrlen(hdr->frame_control); 946e2454948SJohannes Berg 947a26eb27aSJohannes Berg /* internal error, why isn't DONTFRAG set? */ 9488ccd8f21SJohannes Berg if (WARN_ON(skb->len + FCS_LEN <= frag_threshold)) 9492de8e0d9SJohannes Berg return TX_DROP; 950e2454948SJohannes Berg 9512de8e0d9SJohannes Berg /* 9522de8e0d9SJohannes Berg * Now fragment the frame. This will allocate all the fragments and 9532de8e0d9SJohannes Berg * chain them (using skb as the first fragment) to skb->next. 9542de8e0d9SJohannes Berg * During transmission, we will remove the successfully transmitted 9552de8e0d9SJohannes Berg * fragments from this list. When the low-level driver rejects one 9562de8e0d9SJohannes Berg * of the fragments then we will simply pretend to accept the skb 9572de8e0d9SJohannes Berg * but store it away as pending. 9582de8e0d9SJohannes Berg */ 959252b86c4SJohannes Berg if (ieee80211_fragment(tx, skb, hdrlen, frag_threshold)) 9602de8e0d9SJohannes Berg return TX_DROP; 961e2454948SJohannes Berg 9622de8e0d9SJohannes Berg /* update duration/seq/flags of fragments */ 9632de8e0d9SJohannes Berg fragnum = 0; 964252b86c4SJohannes Berg 965252b86c4SJohannes Berg skb_queue_walk(&tx->skbs, skb) { 9662de8e0d9SJohannes Berg const __le16 morefrags = cpu_to_le16(IEEE80211_FCTL_MOREFRAGS); 967e2454948SJohannes Berg 9682de8e0d9SJohannes Berg hdr = (void *)skb->data; 9692de8e0d9SJohannes Berg info = IEEE80211_SKB_CB(skb); 970e6a9854bSJohannes Berg 971252b86c4SJohannes Berg if (!skb_queue_is_last(&tx->skbs, skb)) { 9722de8e0d9SJohannes Berg hdr->frame_control |= morefrags; 973e6a9854bSJohannes Berg /* 974e6a9854bSJohannes Berg * No multi-rate retries for fragmented frames, that 975e6a9854bSJohannes Berg * would completely throw off the NAV at other STAs. 976e6a9854bSJohannes Berg */ 977e6a9854bSJohannes Berg info->control.rates[1].idx = -1; 978e6a9854bSJohannes Berg info->control.rates[2].idx = -1; 979e6a9854bSJohannes Berg info->control.rates[3].idx = -1; 980e3e1a0bcSThomas Huehn BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 4); 981e6a9854bSJohannes Berg info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; 9822de8e0d9SJohannes Berg } else { 9832de8e0d9SJohannes Berg hdr->frame_control &= ~morefrags; 984e6a9854bSJohannes Berg } 9852de8e0d9SJohannes Berg hdr->seq_ctrl |= cpu_to_le16(fragnum & IEEE80211_SCTL_FRAG); 9862de8e0d9SJohannes Berg fragnum++; 987252b86c4SJohannes Berg } 988e2454948SJohannes Berg 989e2454948SJohannes Berg return TX_CONTINUE; 990e2454948SJohannes Berg } 991e2454948SJohannes Berg 992d9e8a70fSJohannes Berg static ieee80211_tx_result debug_noinline 993feff1f2fSJohannes Berg ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) 994feff1f2fSJohannes Berg { 995252b86c4SJohannes Berg struct sk_buff *skb; 996560d2682SJohannes Berg int ac = -1; 997feff1f2fSJohannes Berg 998feff1f2fSJohannes Berg if (!tx->sta) 999feff1f2fSJohannes Berg return TX_CONTINUE; 1000feff1f2fSJohannes Berg 1001252b86c4SJohannes Berg skb_queue_walk(&tx->skbs, skb) { 1002560d2682SJohannes Berg ac = skb_get_queue_mapping(skb); 1003e5a9f8d0SJohannes Berg tx->sta->tx_stats.bytes[ac] += skb->len; 1004252b86c4SJohannes Berg } 1005560d2682SJohannes Berg if (ac >= 0) 1006e5a9f8d0SJohannes Berg tx->sta->tx_stats.packets[ac]++; 1007feff1f2fSJohannes Berg 1008feff1f2fSJohannes Berg return TX_CONTINUE; 1009feff1f2fSJohannes Berg } 1010feff1f2fSJohannes Berg 1011feff1f2fSJohannes Berg static ieee80211_tx_result debug_noinline 1012e2454948SJohannes Berg ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) 1013e2454948SJohannes Berg { 1014e2454948SJohannes Berg if (!tx->key) 1015e2454948SJohannes Berg return TX_CONTINUE; 1016e2454948SJohannes Berg 101797359d12SJohannes Berg switch (tx->key->conf.cipher) { 101897359d12SJohannes Berg case WLAN_CIPHER_SUITE_WEP40: 101997359d12SJohannes Berg case WLAN_CIPHER_SUITE_WEP104: 1020e2454948SJohannes Berg return ieee80211_crypto_wep_encrypt(tx); 102197359d12SJohannes Berg case WLAN_CIPHER_SUITE_TKIP: 1022e2454948SJohannes Berg return ieee80211_crypto_tkip_encrypt(tx); 102397359d12SJohannes Berg case WLAN_CIPHER_SUITE_CCMP: 10242b2ba0dbSJouni Malinen return ieee80211_crypto_ccmp_encrypt( 10252b2ba0dbSJouni Malinen tx, IEEE80211_CCMP_MIC_LEN); 10262b2ba0dbSJouni Malinen case WLAN_CIPHER_SUITE_CCMP_256: 10272b2ba0dbSJouni Malinen return ieee80211_crypto_ccmp_encrypt( 10282b2ba0dbSJouni Malinen tx, IEEE80211_CCMP_256_MIC_LEN); 102997359d12SJohannes Berg case WLAN_CIPHER_SUITE_AES_CMAC: 10303cfcf6acSJouni Malinen return ieee80211_crypto_aes_cmac_encrypt(tx); 103156c52da2SJouni Malinen case WLAN_CIPHER_SUITE_BIP_CMAC_256: 103256c52da2SJouni Malinen return ieee80211_crypto_aes_cmac_256_encrypt(tx); 10338ade538bSJouni Malinen case WLAN_CIPHER_SUITE_BIP_GMAC_128: 10348ade538bSJouni Malinen case WLAN_CIPHER_SUITE_BIP_GMAC_256: 10358ade538bSJouni Malinen return ieee80211_crypto_aes_gmac_encrypt(tx); 103600b9cfa3SJouni Malinen case WLAN_CIPHER_SUITE_GCMP: 103700b9cfa3SJouni Malinen case WLAN_CIPHER_SUITE_GCMP_256: 103800b9cfa3SJouni Malinen return ieee80211_crypto_gcmp_encrypt(tx); 10393ffc2a90SJohannes Berg default: 1040d32a1028SYoni Divinsky return ieee80211_crypto_hw_encrypt(tx); 1041e2454948SJohannes Berg } 1042e2454948SJohannes Berg 1043e2454948SJohannes Berg return TX_DROP; 1044e2454948SJohannes Berg } 1045e2454948SJohannes Berg 1046d9e8a70fSJohannes Berg static ieee80211_tx_result debug_noinline 104703f93c3dSJohannes Berg ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx) 104803f93c3dSJohannes Berg { 1049252b86c4SJohannes Berg struct sk_buff *skb; 10502de8e0d9SJohannes Berg struct ieee80211_hdr *hdr; 10512de8e0d9SJohannes Berg int next_len; 10522de8e0d9SJohannes Berg bool group_addr; 105303f93c3dSJohannes Berg 1054252b86c4SJohannes Berg skb_queue_walk(&tx->skbs, skb) { 10552de8e0d9SJohannes Berg hdr = (void *) skb->data; 10567e0aae47SJouni Malinen if (unlikely(ieee80211_is_pspoll(hdr->frame_control))) 10577e0aae47SJouni Malinen break; /* must not overwrite AID */ 1058252b86c4SJohannes Berg if (!skb_queue_is_last(&tx->skbs, skb)) { 1059252b86c4SJohannes Berg struct sk_buff *next = skb_queue_next(&tx->skbs, skb); 1060252b86c4SJohannes Berg next_len = next->len; 1061252b86c4SJohannes Berg } else 1062252b86c4SJohannes Berg next_len = 0; 10632de8e0d9SJohannes Berg group_addr = is_multicast_ether_addr(hdr->addr1); 106403f93c3dSJohannes Berg 10652de8e0d9SJohannes Berg hdr->duration_id = 1066252b86c4SJohannes Berg ieee80211_duration(tx, skb, group_addr, next_len); 1067252b86c4SJohannes Berg } 106803f93c3dSJohannes Berg 106903f93c3dSJohannes Berg return TX_CONTINUE; 107003f93c3dSJohannes Berg } 107103f93c3dSJohannes Berg 1072e2ebc74dSJohannes Berg /* actual transmit path */ 1073e2ebc74dSJohannes Berg 1074a622ab72SJohannes Berg static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, 1075a622ab72SJohannes Berg struct sk_buff *skb, 1076a622ab72SJohannes Berg struct ieee80211_tx_info *info, 1077a622ab72SJohannes Berg struct tid_ampdu_tx *tid_tx, 1078a622ab72SJohannes Berg int tid) 1079a622ab72SJohannes Berg { 1080a622ab72SJohannes Berg bool queued = false; 1081285fa695SNikolay Martynov bool reset_agg_timer = false; 1082aa454580SHelmut Schaa struct sk_buff *purge_skb = NULL; 1083a622ab72SJohannes Berg 1084a622ab72SJohannes Berg if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) { 1085a622ab72SJohannes Berg info->flags |= IEEE80211_TX_CTL_AMPDU; 1086285fa695SNikolay Martynov reset_agg_timer = true; 10870ab33703SJohannes Berg } else if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { 10880ab33703SJohannes Berg /* 10890ab33703SJohannes Berg * nothing -- this aggregation session is being started 10900ab33703SJohannes Berg * but that might still fail with the driver 10910ab33703SJohannes Berg */ 1092ba8c3d6fSFelix Fietkau } else if (!tx->sta->sta.txq[tid]) { 1093a622ab72SJohannes Berg spin_lock(&tx->sta->lock); 1094a622ab72SJohannes Berg /* 1095a622ab72SJohannes Berg * Need to re-check now, because we may get here 1096a622ab72SJohannes Berg * 1097a622ab72SJohannes Berg * 1) in the window during which the setup is actually 1098a622ab72SJohannes Berg * already done, but not marked yet because not all 1099a622ab72SJohannes Berg * packets are spliced over to the driver pending 1100a622ab72SJohannes Berg * queue yet -- if this happened we acquire the lock 1101a622ab72SJohannes Berg * either before or after the splice happens, but 1102a622ab72SJohannes Berg * need to recheck which of these cases happened. 1103a622ab72SJohannes Berg * 1104a622ab72SJohannes Berg * 2) during session teardown, if the OPERATIONAL bit 1105a622ab72SJohannes Berg * was cleared due to the teardown but the pointer 1106a622ab72SJohannes Berg * hasn't been assigned NULL yet (or we loaded it 1107a622ab72SJohannes Berg * before it was assigned) -- in this case it may 1108a622ab72SJohannes Berg * now be NULL which means we should just let the 1109a622ab72SJohannes Berg * packet pass through because splicing the frames 1110a622ab72SJohannes Berg * back is already done. 1111a622ab72SJohannes Berg */ 111240b275b6SJohannes Berg tid_tx = rcu_dereference_protected_tid_tx(tx->sta, tid); 1113a622ab72SJohannes Berg 1114a622ab72SJohannes Berg if (!tid_tx) { 1115a622ab72SJohannes Berg /* do nothing, let packet pass through */ 1116a622ab72SJohannes Berg } else if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) { 1117a622ab72SJohannes Berg info->flags |= IEEE80211_TX_CTL_AMPDU; 1118285fa695SNikolay Martynov reset_agg_timer = true; 1119a622ab72SJohannes Berg } else { 1120a622ab72SJohannes Berg queued = true; 1121f6d4671aSEmmanuel Grumbach if (info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER) { 1122f6d4671aSEmmanuel Grumbach clear_sta_flag(tx->sta, WLAN_STA_SP); 1123f6d4671aSEmmanuel Grumbach ps_dbg(tx->sta->sdata, 1124f6d4671aSEmmanuel Grumbach "STA %pM aid %d: SP frame queued, close the SP w/o telling the peer\n", 1125f6d4671aSEmmanuel Grumbach tx->sta->sta.addr, tx->sta->sta.aid); 1126f6d4671aSEmmanuel Grumbach } 1127a622ab72SJohannes Berg info->control.vif = &tx->sdata->vif; 1128cc20ff2cSFelix Fietkau info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING; 1129facde7f3SEmmanuel Grumbach info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS; 1130a622ab72SJohannes Berg __skb_queue_tail(&tid_tx->pending, skb); 1131aa454580SHelmut Schaa if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER) 1132aa454580SHelmut Schaa purge_skb = __skb_dequeue(&tid_tx->pending); 1133a622ab72SJohannes Berg } 1134a622ab72SJohannes Berg spin_unlock(&tx->sta->lock); 1135aa454580SHelmut Schaa 1136aa454580SHelmut Schaa if (purge_skb) 1137c3e7724bSFelix Fietkau ieee80211_free_txskb(&tx->local->hw, purge_skb); 1138a622ab72SJohannes Berg } 1139a622ab72SJohannes Berg 1140285fa695SNikolay Martynov /* reset session timer */ 1141914eac24SSara Sharon if (reset_agg_timer) 114212d3952fSFelix Fietkau tid_tx->last_tx = jiffies; 1143285fa695SNikolay Martynov 1144a622ab72SJohannes Berg return queued; 1145a622ab72SJohannes Berg } 1146a622ab72SJohannes Berg 114758d4185eSJohannes Berg /* 114858d4185eSJohannes Berg * initialises @tx 11497c10770fSJohannes Berg * pass %NULL for the station if unknown, a valid pointer if known 11507c10770fSJohannes Berg * or an ERR_PTR() if the station is known not to exist 115158d4185eSJohannes Berg */ 11529ae54c84SJohannes Berg static ieee80211_tx_result 11533b8d81e0SJohannes Berg ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, 11543b8d81e0SJohannes Berg struct ieee80211_tx_data *tx, 11557c10770fSJohannes Berg struct sta_info *sta, struct sk_buff *skb) 1156e2ebc74dSJohannes Berg { 11573b8d81e0SJohannes Berg struct ieee80211_local *local = sdata->local; 115858d4185eSJohannes Berg struct ieee80211_hdr *hdr; 1159e039fa4aSJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 116068f2b517SJohannes Berg int tid; 1161e2ebc74dSJohannes Berg 1162e2ebc74dSJohannes Berg memset(tx, 0, sizeof(*tx)); 1163e2ebc74dSJohannes Berg tx->skb = skb; 1164e2ebc74dSJohannes Berg tx->local = local; 11653b8d81e0SJohannes Berg tx->sdata = sdata; 1166252b86c4SJohannes Berg __skb_queue_head_init(&tx->skbs); 1167e2ebc74dSJohannes Berg 1168cd8ffc80SJohannes Berg /* 1169cd8ffc80SJohannes Berg * If this flag is set to true anywhere, and we get here, 1170cd8ffc80SJohannes Berg * we are doing the needed processing, so remove the flag 1171cd8ffc80SJohannes Berg * now. 1172cd8ffc80SJohannes Berg */ 1173cc20ff2cSFelix Fietkau info->control.flags &= ~IEEE80211_TX_INTCFL_NEED_TXPROCESSING; 1174cd8ffc80SJohannes Berg 117558d4185eSJohannes Berg hdr = (struct ieee80211_hdr *) skb->data; 117658d4185eSJohannes Berg 11777c10770fSJohannes Berg if (likely(sta)) { 11787c10770fSJohannes Berg if (!IS_ERR(sta)) 11797c10770fSJohannes Berg tx->sta = sta; 11807c10770fSJohannes Berg } else { 11813f0e0b22SFelix Fietkau if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { 1182f14543eeSFelix Fietkau tx->sta = rcu_dereference(sdata->u.vlan.sta); 11837c10770fSJohannes Berg if (!tx->sta && sdata->wdev.use_4addr) 11843f0e0b22SFelix Fietkau return TX_DROP; 118510cb8e61SMarkus Theil } else if (tx->sdata->control_port_protocol == tx->skb->protocol) { 1186b4d57adbSFelix Fietkau tx->sta = sta_info_get_bss(sdata, hdr->addr1); 11873f0e0b22SFelix Fietkau } 11889d6b106bSJohannes Berg if (!tx->sta && !is_multicast_ether_addr(hdr->addr1)) 1189abe60632SJohannes Berg tx->sta = sta_info_get(sdata, hdr->addr1); 11907c10770fSJohannes Berg } 119158d4185eSJohannes Berg 1192cd8ffc80SJohannes Berg if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && 119349a59543SJohannes Berg !ieee80211_is_qos_nullfunc(hdr->frame_control) && 119430686bf7SJohannes Berg ieee80211_hw_check(&local->hw, AMPDU_AGGREGATION) && 119530686bf7SJohannes Berg !ieee80211_hw_check(&local->hw, TX_AMPDU_SETUP_IN_HW)) { 1196cd8ffc80SJohannes Berg struct tid_ampdu_tx *tid_tx; 1197cd8ffc80SJohannes Berg 1198a1f2ba04SSara Sharon tid = ieee80211_get_tid(hdr); 11998b30b1feSSujith 1200a622ab72SJohannes Berg tid_tx = rcu_dereference(tx->sta->ampdu_mlme.tid_tx[tid]); 1201a622ab72SJohannes Berg if (tid_tx) { 1202a622ab72SJohannes Berg bool queued; 1203a622ab72SJohannes Berg 1204a622ab72SJohannes Berg queued = ieee80211_tx_prep_agg(tx, skb, info, 1205a622ab72SJohannes Berg tid_tx, tid); 1206cd8ffc80SJohannes Berg 1207cd8ffc80SJohannes Berg if (unlikely(queued)) 1208cd8ffc80SJohannes Berg return TX_QUEUED; 12098b30b1feSSujith } 1210a622ab72SJohannes Berg } 12118b30b1feSSujith 1212badffb72SJiri Slaby if (is_multicast_ether_addr(hdr->addr1)) { 12135cf121c3SJohannes Berg tx->flags &= ~IEEE80211_TX_UNICAST; 1214e039fa4aSJohannes Berg info->flags |= IEEE80211_TX_CTL_NO_ACK; 12156fd67e93SSimon Wunderlich } else 12165cf121c3SJohannes Berg tx->flags |= IEEE80211_TX_UNICAST; 121758d4185eSJohannes Berg 1218a26eb27aSJohannes Berg if (!(info->flags & IEEE80211_TX_CTL_DONTFRAG)) { 1219a26eb27aSJohannes Berg if (!(tx->flags & IEEE80211_TX_UNICAST) || 1220a26eb27aSJohannes Berg skb->len + FCS_LEN <= local->hw.wiphy->frag_threshold || 1221a26eb27aSJohannes Berg info->flags & IEEE80211_TX_CTL_AMPDU) 1222a26eb27aSJohannes Berg info->flags |= IEEE80211_TX_CTL_DONTFRAG; 122358d4185eSJohannes Berg } 122458d4185eSJohannes Berg 1225e2ebc74dSJohannes Berg if (!tx->sta) 1226e039fa4aSJohannes Berg info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; 1227f7418bc1SFelix Fietkau else if (test_and_clear_sta_flag(tx->sta, WLAN_STA_CLEAR_PS_FILT)) { 1228e039fa4aSJohannes Berg info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; 1229f7418bc1SFelix Fietkau ieee80211_check_fast_xmit(tx->sta); 1230f7418bc1SFelix Fietkau } 123158d4185eSJohannes Berg 1232e039fa4aSJohannes Berg info->flags |= IEEE80211_TX_CTL_FIRST_FRAGMENT; 1233e2ebc74dSJohannes Berg 12349ae54c84SJohannes Berg return TX_CONTINUE; 1235e2ebc74dSJohannes Berg } 1236e2ebc74dSJohannes Berg 123780a83cfcSMichal Kazior static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local, 1238ba8c3d6fSFelix Fietkau struct ieee80211_vif *vif, 1239dbef5362SMichal Kazior struct sta_info *sta, 1240ba8c3d6fSFelix Fietkau struct sk_buff *skb) 1241ba8c3d6fSFelix Fietkau { 1242ba8c3d6fSFelix Fietkau struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 1243ba8c3d6fSFelix Fietkau struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1244ba8c3d6fSFelix Fietkau struct ieee80211_txq *txq = NULL; 1245ba8c3d6fSFelix Fietkau 1246c3732a7bSFelix Fietkau if ((info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) || 1247c3732a7bSFelix Fietkau (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE)) 124880a83cfcSMichal Kazior return NULL; 1249ba8c3d6fSFelix Fietkau 1250cc20ff2cSFelix Fietkau if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) && 125150ff477aSJohn Crispin unlikely(!ieee80211_is_data_present(hdr->frame_control))) { 1252adf8ed01SJohannes Berg if ((!ieee80211_is_mgmt(hdr->frame_control) || 12530eeb2b67SSara Sharon ieee80211_is_bufferable_mmpdu(hdr->frame_control) || 12540eeb2b67SSara Sharon vif->type == NL80211_IFTYPE_STATION) && 1255adf8ed01SJohannes Berg sta && sta->uploaded) { 1256adf8ed01SJohannes Berg /* 1257adf8ed01SJohannes Berg * This will be NULL if the driver didn't set the 1258adf8ed01SJohannes Berg * opt-in hardware flag. 1259adf8ed01SJohannes Berg */ 1260adf8ed01SJohannes Berg txq = sta->sta.txq[IEEE80211_NUM_TIDS]; 1261adf8ed01SJohannes Berg } 1262adf8ed01SJohannes Berg } else if (sta) { 1263ba8c3d6fSFelix Fietkau u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; 1264ba8c3d6fSFelix Fietkau 1265dbef5362SMichal Kazior if (!sta->uploaded) 1266dbef5362SMichal Kazior return NULL; 1267dbef5362SMichal Kazior 1268dbef5362SMichal Kazior txq = sta->sta.txq[tid]; 1269ba8c3d6fSFelix Fietkau } else if (vif) { 1270ba8c3d6fSFelix Fietkau txq = vif->txq; 1271ba8c3d6fSFelix Fietkau } 1272ba8c3d6fSFelix Fietkau 1273ba8c3d6fSFelix Fietkau if (!txq) 127480a83cfcSMichal Kazior return NULL; 1275ba8c3d6fSFelix Fietkau 127680a83cfcSMichal Kazior return to_txq_info(txq); 127780a83cfcSMichal Kazior } 1278ba8c3d6fSFelix Fietkau 12795caa328eSMichal Kazior static void ieee80211_set_skb_enqueue_time(struct sk_buff *skb) 12805caa328eSMichal Kazior { 12815caa328eSMichal Kazior IEEE80211_SKB_CB(skb)->control.enqueue_time = codel_get_time(); 12825caa328eSMichal Kazior } 12835caa328eSMichal Kazior 12845caa328eSMichal Kazior static u32 codel_skb_len_func(const struct sk_buff *skb) 12855caa328eSMichal Kazior { 12865caa328eSMichal Kazior return skb->len; 12875caa328eSMichal Kazior } 12885caa328eSMichal Kazior 12895caa328eSMichal Kazior static codel_time_t codel_skb_time_func(const struct sk_buff *skb) 12905caa328eSMichal Kazior { 12915caa328eSMichal Kazior const struct ieee80211_tx_info *info; 12925caa328eSMichal Kazior 12935caa328eSMichal Kazior info = (const struct ieee80211_tx_info *)skb->cb; 12945caa328eSMichal Kazior return info->control.enqueue_time; 12955caa328eSMichal Kazior } 12965caa328eSMichal Kazior 12975caa328eSMichal Kazior static struct sk_buff *codel_dequeue_func(struct codel_vars *cvars, 12985caa328eSMichal Kazior void *ctx) 12995caa328eSMichal Kazior { 13005caa328eSMichal Kazior struct ieee80211_local *local; 13015caa328eSMichal Kazior struct txq_info *txqi; 13025caa328eSMichal Kazior struct fq *fq; 13035caa328eSMichal Kazior struct fq_flow *flow; 13045caa328eSMichal Kazior 13055caa328eSMichal Kazior txqi = ctx; 13065caa328eSMichal Kazior local = vif_to_sdata(txqi->txq.vif)->local; 13075caa328eSMichal Kazior fq = &local->fq; 13085caa328eSMichal Kazior 13095caa328eSMichal Kazior if (cvars == &txqi->def_cvars) 1310bf9009bfSFelix Fietkau flow = &txqi->tin.default_flow; 13115caa328eSMichal Kazior else 13125caa328eSMichal Kazior flow = &fq->flows[cvars - local->cvars]; 13135caa328eSMichal Kazior 13145caa328eSMichal Kazior return fq_flow_dequeue(fq, flow); 13155caa328eSMichal Kazior } 13165caa328eSMichal Kazior 13175caa328eSMichal Kazior static void codel_drop_func(struct sk_buff *skb, 13185caa328eSMichal Kazior void *ctx) 13195caa328eSMichal Kazior { 13205caa328eSMichal Kazior struct ieee80211_local *local; 13215caa328eSMichal Kazior struct ieee80211_hw *hw; 13225caa328eSMichal Kazior struct txq_info *txqi; 13235caa328eSMichal Kazior 13245caa328eSMichal Kazior txqi = ctx; 13255caa328eSMichal Kazior local = vif_to_sdata(txqi->txq.vif)->local; 13265caa328eSMichal Kazior hw = &local->hw; 13275caa328eSMichal Kazior 13285caa328eSMichal Kazior ieee80211_free_txskb(hw, skb); 13295caa328eSMichal Kazior } 13305caa328eSMichal Kazior 1331fa962b92SMichal Kazior static struct sk_buff *fq_tin_dequeue_func(struct fq *fq, 1332fa962b92SMichal Kazior struct fq_tin *tin, 1333fa962b92SMichal Kazior struct fq_flow *flow) 1334fa962b92SMichal Kazior { 13355caa328eSMichal Kazior struct ieee80211_local *local; 13365caa328eSMichal Kazior struct txq_info *txqi; 13375caa328eSMichal Kazior struct codel_vars *cvars; 13385caa328eSMichal Kazior struct codel_params *cparams; 13395caa328eSMichal Kazior struct codel_stats *cstats; 13405caa328eSMichal Kazior 13415caa328eSMichal Kazior local = container_of(fq, struct ieee80211_local, fq); 13425caa328eSMichal Kazior txqi = container_of(tin, struct txq_info, tin); 13438d51dbb8SToke Høiland-Jørgensen cstats = &txqi->cstats; 13445caa328eSMichal Kazior 1345484a54c2SToke Høiland-Jørgensen if (txqi->txq.sta) { 1346484a54c2SToke Høiland-Jørgensen struct sta_info *sta = container_of(txqi->txq.sta, 1347484a54c2SToke Høiland-Jørgensen struct sta_info, sta); 1348484a54c2SToke Høiland-Jørgensen cparams = &sta->cparams; 1349484a54c2SToke Høiland-Jørgensen } else { 1350484a54c2SToke Høiland-Jørgensen cparams = &local->cparams; 1351484a54c2SToke Høiland-Jørgensen } 1352484a54c2SToke Høiland-Jørgensen 1353bf9009bfSFelix Fietkau if (flow == &tin->default_flow) 13545caa328eSMichal Kazior cvars = &txqi->def_cvars; 13555caa328eSMichal Kazior else 13565caa328eSMichal Kazior cvars = &local->cvars[flow - fq->flows]; 13575caa328eSMichal Kazior 13585caa328eSMichal Kazior return codel_dequeue(txqi, 13595caa328eSMichal Kazior &flow->backlog, 13605caa328eSMichal Kazior cparams, 13615caa328eSMichal Kazior cvars, 13625caa328eSMichal Kazior cstats, 13635caa328eSMichal Kazior codel_skb_len_func, 13645caa328eSMichal Kazior codel_skb_time_func, 13655caa328eSMichal Kazior codel_drop_func, 13665caa328eSMichal Kazior codel_dequeue_func); 1367fa962b92SMichal Kazior } 1368fa962b92SMichal Kazior 1369fa962b92SMichal Kazior static void fq_skb_free_func(struct fq *fq, 1370fa962b92SMichal Kazior struct fq_tin *tin, 1371fa962b92SMichal Kazior struct fq_flow *flow, 1372fa962b92SMichal Kazior struct sk_buff *skb) 1373fa962b92SMichal Kazior { 1374fa962b92SMichal Kazior struct ieee80211_local *local; 1375fa962b92SMichal Kazior 1376fa962b92SMichal Kazior local = container_of(fq, struct ieee80211_local, fq); 1377fa962b92SMichal Kazior ieee80211_free_txskb(&local->hw, skb); 1378fa962b92SMichal Kazior } 1379fa962b92SMichal Kazior 138080a83cfcSMichal Kazior static void ieee80211_txq_enqueue(struct ieee80211_local *local, 138180a83cfcSMichal Kazior struct txq_info *txqi, 138280a83cfcSMichal Kazior struct sk_buff *skb) 138380a83cfcSMichal Kazior { 1384fa962b92SMichal Kazior struct fq *fq = &local->fq; 1385fa962b92SMichal Kazior struct fq_tin *tin = &txqi->tin; 1386f2af2df8SFelix Fietkau u32 flow_idx = fq_flow_idx(fq, skb); 138780a83cfcSMichal Kazior 13885caa328eSMichal Kazior ieee80211_set_skb_enqueue_time(skb); 1389f2af2df8SFelix Fietkau 1390f2af2df8SFelix Fietkau spin_lock_bh(&fq->lock); 139173bc9e0aSJohannes Berg /* 139273bc9e0aSJohannes Berg * For management frames, don't really apply codel etc., 139373bc9e0aSJohannes Berg * we don't want to apply any shaping or anything we just 139473bc9e0aSJohannes Berg * want to simplify the driver API by having them on the 139573bc9e0aSJohannes Berg * txqi. 139673bc9e0aSJohannes Berg */ 1397ca47b462SJohannes Berg if (unlikely(txqi->txq.tid == IEEE80211_NUM_TIDS)) { 1398ca47b462SJohannes Berg IEEE80211_SKB_CB(skb)->control.flags |= 1399ca47b462SJohannes Berg IEEE80211_TX_INTCFL_NEED_TXPROCESSING; 140073bc9e0aSJohannes Berg __skb_queue_tail(&txqi->frags, skb); 1401ca47b462SJohannes Berg } else { 1402f2af2df8SFelix Fietkau fq_tin_enqueue(fq, tin, flow_idx, skb, 1403bf9009bfSFelix Fietkau fq_skb_free_func); 1404ca47b462SJohannes Berg } 1405f2af2df8SFelix Fietkau spin_unlock_bh(&fq->lock); 140680a83cfcSMichal Kazior } 140780a83cfcSMichal Kazior 14082a9e2579SJohannes Berg static bool fq_vlan_filter_func(struct fq *fq, struct fq_tin *tin, 14092a9e2579SJohannes Berg struct fq_flow *flow, struct sk_buff *skb, 14102a9e2579SJohannes Berg void *data) 14112a9e2579SJohannes Berg { 14122a9e2579SJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 14132a9e2579SJohannes Berg 14142a9e2579SJohannes Berg return info->control.vif == data; 14152a9e2579SJohannes Berg } 14162a9e2579SJohannes Berg 14172a9e2579SJohannes Berg void ieee80211_txq_remove_vlan(struct ieee80211_local *local, 14182a9e2579SJohannes Berg struct ieee80211_sub_if_data *sdata) 14192a9e2579SJohannes Berg { 14202a9e2579SJohannes Berg struct fq *fq = &local->fq; 14212a9e2579SJohannes Berg struct txq_info *txqi; 14222a9e2579SJohannes Berg struct fq_tin *tin; 14232a9e2579SJohannes Berg struct ieee80211_sub_if_data *ap; 14242a9e2579SJohannes Berg 14252a9e2579SJohannes Berg if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN)) 14262a9e2579SJohannes Berg return; 14272a9e2579SJohannes Berg 14282a9e2579SJohannes Berg ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); 14292a9e2579SJohannes Berg 14302a9e2579SJohannes Berg if (!ap->vif.txq) 14312a9e2579SJohannes Berg return; 14322a9e2579SJohannes Berg 14332a9e2579SJohannes Berg txqi = to_txq_info(ap->vif.txq); 14342a9e2579SJohannes Berg tin = &txqi->tin; 14352a9e2579SJohannes Berg 14362a9e2579SJohannes Berg spin_lock_bh(&fq->lock); 14372a9e2579SJohannes Berg fq_tin_filter(fq, tin, fq_vlan_filter_func, &sdata->vif, 14382a9e2579SJohannes Berg fq_skb_free_func); 14392a9e2579SJohannes Berg spin_unlock_bh(&fq->lock); 14402a9e2579SJohannes Berg } 14412a9e2579SJohannes Berg 1442fa962b92SMichal Kazior void ieee80211_txq_init(struct ieee80211_sub_if_data *sdata, 1443fa962b92SMichal Kazior struct sta_info *sta, 1444fa962b92SMichal Kazior struct txq_info *txqi, int tid) 1445fa962b92SMichal Kazior { 1446fa962b92SMichal Kazior fq_tin_init(&txqi->tin); 14475caa328eSMichal Kazior codel_vars_init(&txqi->def_cvars); 14488d51dbb8SToke Høiland-Jørgensen codel_stats_init(&txqi->cstats); 1449bb42f2d1SToke Høiland-Jørgensen __skb_queue_head_init(&txqi->frags); 145018667600SToke Høiland-Jørgensen INIT_LIST_HEAD(&txqi->schedule_order); 1451fa962b92SMichal Kazior 1452fa962b92SMichal Kazior txqi->txq.vif = &sdata->vif; 1453fa962b92SMichal Kazior 1454adf8ed01SJohannes Berg if (!sta) { 1455fa962b92SMichal Kazior sdata->vif.txq = &txqi->txq; 1456fa962b92SMichal Kazior txqi->txq.tid = 0; 1457fa962b92SMichal Kazior txqi->txq.ac = IEEE80211_AC_BE; 1458adf8ed01SJohannes Berg 1459adf8ed01SJohannes Berg return; 1460fa962b92SMichal Kazior } 1461adf8ed01SJohannes Berg 1462adf8ed01SJohannes Berg if (tid == IEEE80211_NUM_TIDS) { 14630eeb2b67SSara Sharon if (sdata->vif.type == NL80211_IFTYPE_STATION) { 14640eeb2b67SSara Sharon /* Drivers need to opt in to the management MPDU TXQ */ 14650eeb2b67SSara Sharon if (!ieee80211_hw_check(&sdata->local->hw, 14660eeb2b67SSara Sharon STA_MMPDU_TXQ)) 1467adf8ed01SJohannes Berg return; 14680eeb2b67SSara Sharon } else if (!ieee80211_hw_check(&sdata->local->hw, 14690eeb2b67SSara Sharon BUFF_MMPDU_TXQ)) { 14700eeb2b67SSara Sharon /* Drivers need to opt in to the bufferable MMPDU TXQ */ 14710eeb2b67SSara Sharon return; 14720eeb2b67SSara Sharon } 1473adf8ed01SJohannes Berg txqi->txq.ac = IEEE80211_AC_VO; 1474adf8ed01SJohannes Berg } else { 1475adf8ed01SJohannes Berg txqi->txq.ac = ieee80211_ac_from_tid(tid); 1476adf8ed01SJohannes Berg } 1477adf8ed01SJohannes Berg 1478adf8ed01SJohannes Berg txqi->txq.sta = &sta->sta; 1479adf8ed01SJohannes Berg txqi->txq.tid = tid; 1480adf8ed01SJohannes Berg sta->sta.txq[tid] = &txqi->txq; 1481fa962b92SMichal Kazior } 1482fa962b92SMichal Kazior 1483fa962b92SMichal Kazior void ieee80211_txq_purge(struct ieee80211_local *local, 1484fa962b92SMichal Kazior struct txq_info *txqi) 1485fa962b92SMichal Kazior { 1486fa962b92SMichal Kazior struct fq *fq = &local->fq; 1487fa962b92SMichal Kazior struct fq_tin *tin = &txqi->tin; 1488fa962b92SMichal Kazior 1489b4809e94SToke Høiland-Jørgensen spin_lock_bh(&fq->lock); 1490fa962b92SMichal Kazior fq_tin_reset(fq, tin, fq_skb_free_func); 1491bb42f2d1SToke Høiland-Jørgensen ieee80211_purge_tx_queue(&local->hw, &txqi->frags); 1492b4809e94SToke Høiland-Jørgensen spin_unlock_bh(&fq->lock); 1493b4809e94SToke Høiland-Jørgensen 149418667600SToke Høiland-Jørgensen spin_lock_bh(&local->active_txq_lock[txqi->txq.ac]); 149518667600SToke Høiland-Jørgensen list_del_init(&txqi->schedule_order); 149618667600SToke Høiland-Jørgensen spin_unlock_bh(&local->active_txq_lock[txqi->txq.ac]); 1497fa962b92SMichal Kazior } 1498fa962b92SMichal Kazior 14992fe4a29aSToke Høiland-Jørgensen void ieee80211_txq_set_params(struct ieee80211_local *local) 15002fe4a29aSToke Høiland-Jørgensen { 15012fe4a29aSToke Høiland-Jørgensen if (local->hw.wiphy->txq_limit) 15022fe4a29aSToke Høiland-Jørgensen local->fq.limit = local->hw.wiphy->txq_limit; 15032fe4a29aSToke Høiland-Jørgensen else 15042fe4a29aSToke Høiland-Jørgensen local->hw.wiphy->txq_limit = local->fq.limit; 15052fe4a29aSToke Høiland-Jørgensen 15062fe4a29aSToke Høiland-Jørgensen if (local->hw.wiphy->txq_memory_limit) 15072fe4a29aSToke Høiland-Jørgensen local->fq.memory_limit = local->hw.wiphy->txq_memory_limit; 15082fe4a29aSToke Høiland-Jørgensen else 15092fe4a29aSToke Høiland-Jørgensen local->hw.wiphy->txq_memory_limit = local->fq.memory_limit; 15102fe4a29aSToke Høiland-Jørgensen 15112fe4a29aSToke Høiland-Jørgensen if (local->hw.wiphy->txq_quantum) 15122fe4a29aSToke Høiland-Jørgensen local->fq.quantum = local->hw.wiphy->txq_quantum; 15132fe4a29aSToke Høiland-Jørgensen else 15142fe4a29aSToke Høiland-Jørgensen local->hw.wiphy->txq_quantum = local->fq.quantum; 15152fe4a29aSToke Høiland-Jørgensen } 15162fe4a29aSToke Høiland-Jørgensen 1517fa962b92SMichal Kazior int ieee80211_txq_setup_flows(struct ieee80211_local *local) 1518fa962b92SMichal Kazior { 1519fa962b92SMichal Kazior struct fq *fq = &local->fq; 1520fa962b92SMichal Kazior int ret; 15215caa328eSMichal Kazior int i; 15223ff23cd5SToke Høiland-Jørgensen bool supp_vht = false; 15233ff23cd5SToke Høiland-Jørgensen enum nl80211_band band; 1524fa962b92SMichal Kazior 1525fa962b92SMichal Kazior if (!local->ops->wake_tx_queue) 1526fa962b92SMichal Kazior return 0; 1527fa962b92SMichal Kazior 1528fa962b92SMichal Kazior ret = fq_init(fq, 4096); 1529fa962b92SMichal Kazior if (ret) 1530fa962b92SMichal Kazior return ret; 1531fa962b92SMichal Kazior 15323ff23cd5SToke Høiland-Jørgensen /* 15333ff23cd5SToke Høiland-Jørgensen * If the hardware doesn't support VHT, it is safe to limit the maximum 15343ff23cd5SToke Høiland-Jørgensen * queue size. 4 Mbytes is 64 max-size aggregates in 802.11n. 15353ff23cd5SToke Høiland-Jørgensen */ 15363ff23cd5SToke Høiland-Jørgensen for (band = 0; band < NUM_NL80211_BANDS; band++) { 15373ff23cd5SToke Høiland-Jørgensen struct ieee80211_supported_band *sband; 15383ff23cd5SToke Høiland-Jørgensen 15393ff23cd5SToke Høiland-Jørgensen sband = local->hw.wiphy->bands[band]; 15403ff23cd5SToke Høiland-Jørgensen if (!sband) 15413ff23cd5SToke Høiland-Jørgensen continue; 15423ff23cd5SToke Høiland-Jørgensen 15433ff23cd5SToke Høiland-Jørgensen supp_vht = supp_vht || sband->vht_cap.vht_supported; 15443ff23cd5SToke Høiland-Jørgensen } 15453ff23cd5SToke Høiland-Jørgensen 15463ff23cd5SToke Høiland-Jørgensen if (!supp_vht) 15473ff23cd5SToke Høiland-Jørgensen fq->memory_limit = 4 << 20; /* 4 Mbytes */ 15483ff23cd5SToke Høiland-Jørgensen 15495caa328eSMichal Kazior codel_params_init(&local->cparams); 15505caa328eSMichal Kazior local->cparams.interval = MS2TIME(100); 15515caa328eSMichal Kazior local->cparams.target = MS2TIME(20); 15525caa328eSMichal Kazior local->cparams.ecn = true; 15535caa328eSMichal Kazior 15545caa328eSMichal Kazior local->cvars = kcalloc(fq->flows_cnt, sizeof(local->cvars[0]), 15555caa328eSMichal Kazior GFP_KERNEL); 15565caa328eSMichal Kazior if (!local->cvars) { 155759a7c828SMichal Kazior spin_lock_bh(&fq->lock); 15585caa328eSMichal Kazior fq_reset(fq, fq_skb_free_func); 155959a7c828SMichal Kazior spin_unlock_bh(&fq->lock); 15605caa328eSMichal Kazior return -ENOMEM; 15615caa328eSMichal Kazior } 15625caa328eSMichal Kazior 15635caa328eSMichal Kazior for (i = 0; i < fq->flows_cnt; i++) 15645caa328eSMichal Kazior codel_vars_init(&local->cvars[i]); 15655caa328eSMichal Kazior 15662fe4a29aSToke Høiland-Jørgensen ieee80211_txq_set_params(local); 15672fe4a29aSToke Høiland-Jørgensen 1568fa962b92SMichal Kazior return 0; 1569fa962b92SMichal Kazior } 1570fa962b92SMichal Kazior 1571fa962b92SMichal Kazior void ieee80211_txq_teardown_flows(struct ieee80211_local *local) 1572fa962b92SMichal Kazior { 1573fa962b92SMichal Kazior struct fq *fq = &local->fq; 1574fa962b92SMichal Kazior 1575fa962b92SMichal Kazior if (!local->ops->wake_tx_queue) 1576fa962b92SMichal Kazior return; 1577fa962b92SMichal Kazior 15785caa328eSMichal Kazior kfree(local->cvars); 15795caa328eSMichal Kazior local->cvars = NULL; 15805caa328eSMichal Kazior 158159a7c828SMichal Kazior spin_lock_bh(&fq->lock); 1582fa962b92SMichal Kazior fq_reset(fq, fq_skb_free_func); 158359a7c828SMichal Kazior spin_unlock_bh(&fq->lock); 1584ba8c3d6fSFelix Fietkau } 1585ba8c3d6fSFelix Fietkau 1586bb42f2d1SToke Høiland-Jørgensen static bool ieee80211_queue_skb(struct ieee80211_local *local, 1587bb42f2d1SToke Høiland-Jørgensen struct ieee80211_sub_if_data *sdata, 1588bb42f2d1SToke Høiland-Jørgensen struct sta_info *sta, 1589bb42f2d1SToke Høiland-Jørgensen struct sk_buff *skb) 1590bb42f2d1SToke Høiland-Jørgensen { 1591bb42f2d1SToke Høiland-Jørgensen struct ieee80211_vif *vif; 1592bb42f2d1SToke Høiland-Jørgensen struct txq_info *txqi; 1593bb42f2d1SToke Høiland-Jørgensen 1594bb42f2d1SToke Høiland-Jørgensen if (!local->ops->wake_tx_queue || 1595bb42f2d1SToke Høiland-Jørgensen sdata->vif.type == NL80211_IFTYPE_MONITOR) 1596bb42f2d1SToke Høiland-Jørgensen return false; 1597bb42f2d1SToke Høiland-Jørgensen 1598bb42f2d1SToke Høiland-Jørgensen if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 1599bb42f2d1SToke Høiland-Jørgensen sdata = container_of(sdata->bss, 1600bb42f2d1SToke Høiland-Jørgensen struct ieee80211_sub_if_data, u.ap); 1601bb42f2d1SToke Høiland-Jørgensen 1602bb42f2d1SToke Høiland-Jørgensen vif = &sdata->vif; 1603dbef5362SMichal Kazior txqi = ieee80211_get_txq(local, vif, sta, skb); 1604bb42f2d1SToke Høiland-Jørgensen 1605bb42f2d1SToke Høiland-Jørgensen if (!txqi) 1606bb42f2d1SToke Høiland-Jørgensen return false; 1607bb42f2d1SToke Høiland-Jørgensen 1608bb42f2d1SToke Høiland-Jørgensen ieee80211_txq_enqueue(local, txqi, skb); 1609bb42f2d1SToke Høiland-Jørgensen 161018667600SToke Høiland-Jørgensen schedule_and_wake_txq(local, txqi); 1611bb42f2d1SToke Høiland-Jørgensen 1612bb42f2d1SToke Høiland-Jørgensen return true; 1613bb42f2d1SToke Høiland-Jørgensen } 1614bb42f2d1SToke Høiland-Jørgensen 161511127e91SJohannes Berg static bool ieee80211_tx_frags(struct ieee80211_local *local, 161611127e91SJohannes Berg struct ieee80211_vif *vif, 16174fd0328dSJohannes Berg struct sta_info *sta, 161811127e91SJohannes Berg struct sk_buff_head *skbs, 161911127e91SJohannes Berg bool txpending) 1620e2ebc74dSJohannes Berg { 162180a83cfcSMichal Kazior struct ieee80211_tx_control control = {}; 1622252b86c4SJohannes Berg struct sk_buff *skb, *tmp; 16233b8d81e0SJohannes Berg unsigned long flags; 1624e2ebc74dSJohannes Berg 1625252b86c4SJohannes Berg skb_queue_walk_safe(skbs, skb, tmp) { 16263a25a8c8SJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 16273a25a8c8SJohannes Berg int q = info->hw_queue; 16283a25a8c8SJohannes Berg 16293a25a8c8SJohannes Berg #ifdef CONFIG_MAC80211_VERBOSE_DEBUG 16303a25a8c8SJohannes Berg if (WARN_ON_ONCE(q >= local->hw.queues)) { 16313a25a8c8SJohannes Berg __skb_unlink(skb, skbs); 1632c3e7724bSFelix Fietkau ieee80211_free_txskb(&local->hw, skb); 16333a25a8c8SJohannes Berg continue; 16343a25a8c8SJohannes Berg } 16353a25a8c8SJohannes Berg #endif 16363b8d81e0SJohannes Berg 16373b8d81e0SJohannes Berg spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 16383b8d81e0SJohannes Berg if (local->queue_stop_reasons[q] || 16397bb45683SJohannes Berg (!txpending && !skb_queue_empty(&local->pending[q]))) { 16406c17b77bSSeth Forshee if (unlikely(info->flags & 1641a7679ed5SSeth Forshee IEEE80211_TX_INTFL_OFFCHAN_TX_OK)) { 1642a7679ed5SSeth Forshee if (local->queue_stop_reasons[q] & 1643a7679ed5SSeth Forshee ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL)) { 16446c17b77bSSeth Forshee /* 1645a7679ed5SSeth Forshee * Drop off-channel frames if queues 1646a7679ed5SSeth Forshee * are stopped for any reason other 1647a7679ed5SSeth Forshee * than off-channel operation. Never 1648a7679ed5SSeth Forshee * queue them. 16496c17b77bSSeth Forshee */ 16506c17b77bSSeth Forshee spin_unlock_irqrestore( 1651a7679ed5SSeth Forshee &local->queue_stop_reason_lock, 1652a7679ed5SSeth Forshee flags); 1653a7679ed5SSeth Forshee ieee80211_purge_tx_queue(&local->hw, 1654a7679ed5SSeth Forshee skbs); 16556c17b77bSSeth Forshee return true; 16566c17b77bSSeth Forshee } 1657a7679ed5SSeth Forshee } else { 16586c17b77bSSeth Forshee 16597bb45683SJohannes Berg /* 1660a7679ed5SSeth Forshee * Since queue is stopped, queue up frames for 1661a7679ed5SSeth Forshee * later transmission from the tx-pending 1662a7679ed5SSeth Forshee * tasklet when the queue is woken again. 16637bb45683SJohannes Berg */ 1664252b86c4SJohannes Berg if (txpending) 1665a7679ed5SSeth Forshee skb_queue_splice_init(skbs, 1666a7679ed5SSeth Forshee &local->pending[q]); 16677bb45683SJohannes Berg else 16684db4e0a1SJohannes Berg skb_queue_splice_tail_init(skbs, 16694db4e0a1SJohannes Berg &local->pending[q]); 16707bb45683SJohannes Berg 16717bb45683SJohannes Berg spin_unlock_irqrestore(&local->queue_stop_reason_lock, 16727bb45683SJohannes Berg flags); 16737bb45683SJohannes Berg return false; 16747bb45683SJohannes Berg } 1675a7679ed5SSeth Forshee } 16763b8d81e0SJohannes Berg spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 1677e2530083SJohannes Berg 167811127e91SJohannes Berg info->control.vif = vif; 16794fd0328dSJohannes Berg control.sta = sta ? &sta->sta : NULL; 1680ec25acc4SJohannes Berg 1681252b86c4SJohannes Berg __skb_unlink(skb, skbs); 168280a83cfcSMichal Kazior drv_tx(local, &control, skb); 1683e2ebc74dSJohannes Berg } 16842de8e0d9SJohannes Berg 168511127e91SJohannes Berg return true; 168611127e91SJohannes Berg } 168711127e91SJohannes Berg 168811127e91SJohannes Berg /* 168911127e91SJohannes Berg * Returns false if the frame couldn't be transmitted but was queued instead. 169011127e91SJohannes Berg */ 169111127e91SJohannes Berg static bool __ieee80211_tx(struct ieee80211_local *local, 169211127e91SJohannes Berg struct sk_buff_head *skbs, int led_len, 169311127e91SJohannes Berg struct sta_info *sta, bool txpending) 169411127e91SJohannes Berg { 169511127e91SJohannes Berg struct ieee80211_tx_info *info; 169611127e91SJohannes Berg struct ieee80211_sub_if_data *sdata; 169711127e91SJohannes Berg struct ieee80211_vif *vif; 169811127e91SJohannes Berg struct sk_buff *skb; 1699958574cbSColin Ian King bool result; 170011127e91SJohannes Berg __le16 fc; 170111127e91SJohannes Berg 170211127e91SJohannes Berg if (WARN_ON(skb_queue_empty(skbs))) 170311127e91SJohannes Berg return true; 170411127e91SJohannes Berg 170511127e91SJohannes Berg skb = skb_peek(skbs); 170611127e91SJohannes Berg fc = ((struct ieee80211_hdr *)skb->data)->frame_control; 170711127e91SJohannes Berg info = IEEE80211_SKB_CB(skb); 170811127e91SJohannes Berg sdata = vif_to_sdata(info->control.vif); 170911127e91SJohannes Berg if (sta && !sta->uploaded) 171011127e91SJohannes Berg sta = NULL; 171111127e91SJohannes Berg 171211127e91SJohannes Berg switch (sdata->vif.type) { 171311127e91SJohannes Berg case NL80211_IFTYPE_MONITOR: 1714d8212184SAviya Erenfeld if (sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) { 1715c82b5a74SJohannes Berg vif = &sdata->vif; 1716c82b5a74SJohannes Berg break; 1717c82b5a74SJohannes Berg } 17184b6f1dd6SJohannes Berg sdata = rcu_dereference(local->monitor_sdata); 17193a25a8c8SJohannes Berg if (sdata) { 17204b6f1dd6SJohannes Berg vif = &sdata->vif; 17213a25a8c8SJohannes Berg info->hw_queue = 17223a25a8c8SJohannes Berg vif->hw_queue[skb_get_queue_mapping(skb)]; 172330686bf7SJohannes Berg } else if (ieee80211_hw_check(&local->hw, QUEUE_CONTROL)) { 172463b4d8b3SJohannes Berg ieee80211_purge_tx_queue(&local->hw, skbs); 17253a25a8c8SJohannes Berg return true; 17263a25a8c8SJohannes Berg } else 172711127e91SJohannes Berg vif = NULL; 172811127e91SJohannes Berg break; 172911127e91SJohannes Berg case NL80211_IFTYPE_AP_VLAN: 173011127e91SJohannes Berg sdata = container_of(sdata->bss, 173111127e91SJohannes Berg struct ieee80211_sub_if_data, u.ap); 1732fc0561dcSGustavo A. R. Silva fallthrough; 173311127e91SJohannes Berg default: 173411127e91SJohannes Berg vif = &sdata->vif; 173511127e91SJohannes Berg break; 173611127e91SJohannes Berg } 173711127e91SJohannes Berg 17384fd0328dSJohannes Berg result = ieee80211_tx_frags(local, vif, sta, skbs, txpending); 173911127e91SJohannes Berg 174074e4dbfdSJohannes Berg ieee80211_tpt_led_trig_tx(local, fc, led_len); 174174e4dbfdSJohannes Berg 17424db4e0a1SJohannes Berg WARN_ON_ONCE(!skb_queue_empty(skbs)); 1743252b86c4SJohannes Berg 174411127e91SJohannes Berg return result; 1745e2ebc74dSJohannes Berg } 1746e2ebc74dSJohannes Berg 174797b045d6SJohannes Berg /* 174897b045d6SJohannes Berg * Invoke TX handlers, return 0 on success and non-zero if the 174997b045d6SJohannes Berg * frame was dropped or queued. 1750bb42f2d1SToke Høiland-Jørgensen * 1751bb42f2d1SToke Høiland-Jørgensen * The handlers are split into an early and late part. The latter is everything 1752bb42f2d1SToke Høiland-Jørgensen * that can be sensitive to reordering, and will be deferred to after packets 1753bb42f2d1SToke Høiland-Jørgensen * are dequeued from the intermediate queues (when they are enabled). 175497b045d6SJohannes Berg */ 1755bb42f2d1SToke Høiland-Jørgensen static int invoke_tx_handlers_early(struct ieee80211_tx_data *tx) 175697b045d6SJohannes Berg { 175797b045d6SJohannes Berg ieee80211_tx_result res = TX_DROP; 175897b045d6SJohannes Berg 1759d9e8a70fSJohannes Berg #define CALL_TXH(txh) \ 17609aa4aee3SJohannes Berg do { \ 1761d9e8a70fSJohannes Berg res = txh(tx); \ 1762d9e8a70fSJohannes Berg if (res != TX_CONTINUE) \ 17639aa4aee3SJohannes Berg goto txh_done; \ 17649aa4aee3SJohannes Berg } while (0) 176597b045d6SJohannes Berg 17665c1b98a5SKalle Valo CALL_TXH(ieee80211_tx_h_dynamic_ps); 17679aa4aee3SJohannes Berg CALL_TXH(ieee80211_tx_h_check_assoc); 17689aa4aee3SJohannes Berg CALL_TXH(ieee80211_tx_h_ps_buf); 1769a621fa4dSJohannes Berg CALL_TXH(ieee80211_tx_h_check_control_port_protocol); 17709aa4aee3SJohannes Berg CALL_TXH(ieee80211_tx_h_select_key); 1771c6fcf6bcSJohannes Berg 1772bb42f2d1SToke Høiland-Jørgensen txh_done: 1773bb42f2d1SToke Høiland-Jørgensen if (unlikely(res == TX_DROP)) { 1774bb42f2d1SToke Høiland-Jørgensen I802_DEBUG_INC(tx->local->tx_handlers_drop); 1775bb42f2d1SToke Høiland-Jørgensen if (tx->skb) 1776bb42f2d1SToke Høiland-Jørgensen ieee80211_free_txskb(&tx->local->hw, tx->skb); 1777bb42f2d1SToke Høiland-Jørgensen else 1778bb42f2d1SToke Høiland-Jørgensen ieee80211_purge_tx_queue(&tx->local->hw, &tx->skbs); 1779bb42f2d1SToke Høiland-Jørgensen return -1; 1780bb42f2d1SToke Høiland-Jørgensen } else if (unlikely(res == TX_QUEUED)) { 1781bb42f2d1SToke Høiland-Jørgensen I802_DEBUG_INC(tx->local->tx_handlers_queued); 1782bb42f2d1SToke Høiland-Jørgensen return -1; 1783bb42f2d1SToke Høiland-Jørgensen } 1784bb42f2d1SToke Høiland-Jørgensen 1785bb42f2d1SToke Høiland-Jørgensen return 0; 1786bb42f2d1SToke Høiland-Jørgensen } 1787bb42f2d1SToke Høiland-Jørgensen 1788bb42f2d1SToke Høiland-Jørgensen /* 1789bb42f2d1SToke Høiland-Jørgensen * Late handlers can be called while the sta lock is held. Handlers that can 1790bb42f2d1SToke Høiland-Jørgensen * cause packets to be generated will cause deadlock! 1791bb42f2d1SToke Høiland-Jørgensen */ 1792bb42f2d1SToke Høiland-Jørgensen static int invoke_tx_handlers_late(struct ieee80211_tx_data *tx) 1793bb42f2d1SToke Høiland-Jørgensen { 1794bb42f2d1SToke Høiland-Jørgensen struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); 1795bb42f2d1SToke Høiland-Jørgensen ieee80211_tx_result res = TX_CONTINUE; 1796bb42f2d1SToke Høiland-Jørgensen 1797aa5b5492SJohannes Berg if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION)) { 1798aa5b5492SJohannes Berg __skb_queue_tail(&tx->skbs, tx->skb); 1799aa5b5492SJohannes Berg tx->skb = NULL; 1800c6fcf6bcSJohannes Berg goto txh_done; 1801aa5b5492SJohannes Berg } 1802c6fcf6bcSJohannes Berg 1803*03c3911dSRyder Lee if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL)) 1804*03c3911dSRyder Lee CALL_TXH(ieee80211_tx_h_rate_ctrl); 1805*03c3911dSRyder Lee 1806c6fcf6bcSJohannes Berg CALL_TXH(ieee80211_tx_h_michael_mic_add); 18079aa4aee3SJohannes Berg CALL_TXH(ieee80211_tx_h_sequence); 18089aa4aee3SJohannes Berg CALL_TXH(ieee80211_tx_h_fragment); 1809d9e8a70fSJohannes Berg /* handlers after fragment must be aware of tx info fragmentation! */ 18109aa4aee3SJohannes Berg CALL_TXH(ieee80211_tx_h_stats); 18119aa4aee3SJohannes Berg CALL_TXH(ieee80211_tx_h_encrypt); 181230686bf7SJohannes Berg if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL)) 18139aa4aee3SJohannes Berg CALL_TXH(ieee80211_tx_h_calculate_duration); 1814d9e8a70fSJohannes Berg #undef CALL_TXH 1815d9e8a70fSJohannes Berg 1816d9e8a70fSJohannes Berg txh_done: 181797b045d6SJohannes Berg if (unlikely(res == TX_DROP)) { 18185479d0e7STomas Winkler I802_DEBUG_INC(tx->local->tx_handlers_drop); 1819252b86c4SJohannes Berg if (tx->skb) 1820c3e7724bSFelix Fietkau ieee80211_free_txskb(&tx->local->hw, tx->skb); 1821252b86c4SJohannes Berg else 18221f98ab7fSFelix Fietkau ieee80211_purge_tx_queue(&tx->local->hw, &tx->skbs); 182397b045d6SJohannes Berg return -1; 182497b045d6SJohannes Berg } else if (unlikely(res == TX_QUEUED)) { 18255479d0e7STomas Winkler I802_DEBUG_INC(tx->local->tx_handlers_queued); 182697b045d6SJohannes Berg return -1; 182797b045d6SJohannes Berg } 182897b045d6SJohannes Berg 182997b045d6SJohannes Berg return 0; 183097b045d6SJohannes Berg } 183197b045d6SJohannes Berg 1832bb42f2d1SToke Høiland-Jørgensen static int invoke_tx_handlers(struct ieee80211_tx_data *tx) 1833bb42f2d1SToke Høiland-Jørgensen { 1834bb42f2d1SToke Høiland-Jørgensen int r = invoke_tx_handlers_early(tx); 1835bb42f2d1SToke Høiland-Jørgensen 1836bb42f2d1SToke Høiland-Jørgensen if (r) 1837bb42f2d1SToke Høiland-Jørgensen return r; 1838bb42f2d1SToke Høiland-Jørgensen return invoke_tx_handlers_late(tx); 1839bb42f2d1SToke Høiland-Jørgensen } 1840bb42f2d1SToke Høiland-Jørgensen 184106be6b14SFelix Fietkau bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw, 184206be6b14SFelix Fietkau struct ieee80211_vif *vif, struct sk_buff *skb, 184306be6b14SFelix Fietkau int band, struct ieee80211_sta **sta) 184406be6b14SFelix Fietkau { 184506be6b14SFelix Fietkau struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 184606be6b14SFelix Fietkau struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 184706be6b14SFelix Fietkau struct ieee80211_tx_data tx; 184888724a81SJohannes Berg struct sk_buff *skb2; 184906be6b14SFelix Fietkau 18507c10770fSJohannes Berg if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP) 185106be6b14SFelix Fietkau return false; 185206be6b14SFelix Fietkau 185306be6b14SFelix Fietkau info->band = band; 185406be6b14SFelix Fietkau info->control.vif = vif; 185506be6b14SFelix Fietkau info->hw_queue = vif->hw_queue[skb_get_queue_mapping(skb)]; 185606be6b14SFelix Fietkau 185706be6b14SFelix Fietkau if (invoke_tx_handlers(&tx)) 185806be6b14SFelix Fietkau return false; 185906be6b14SFelix Fietkau 186006be6b14SFelix Fietkau if (sta) { 186106be6b14SFelix Fietkau if (tx.sta) 186206be6b14SFelix Fietkau *sta = &tx.sta->sta; 186306be6b14SFelix Fietkau else 186406be6b14SFelix Fietkau *sta = NULL; 186506be6b14SFelix Fietkau } 186606be6b14SFelix Fietkau 186788724a81SJohannes Berg /* this function isn't suitable for fragmented data frames */ 186888724a81SJohannes Berg skb2 = __skb_dequeue(&tx.skbs); 186988724a81SJohannes Berg if (WARN_ON(skb2 != skb || !skb_queue_empty(&tx.skbs))) { 187088724a81SJohannes Berg ieee80211_free_txskb(hw, skb2); 187188724a81SJohannes Berg ieee80211_purge_tx_queue(hw, &tx.skbs); 187288724a81SJohannes Berg return false; 187388724a81SJohannes Berg } 187488724a81SJohannes Berg 187506be6b14SFelix Fietkau return true; 187606be6b14SFelix Fietkau } 187706be6b14SFelix Fietkau EXPORT_SYMBOL(ieee80211_tx_prepare_skb); 187806be6b14SFelix Fietkau 18797bb45683SJohannes Berg /* 18807bb45683SJohannes Berg * Returns false if the frame couldn't be transmitted but was queued instead. 18817bb45683SJohannes Berg */ 18827bb45683SJohannes Berg static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, 18837c10770fSJohannes Berg struct sta_info *sta, struct sk_buff *skb, 188408aca29aSMathy Vanhoef bool txpending) 1885e2ebc74dSJohannes Berg { 18863b8d81e0SJohannes Berg struct ieee80211_local *local = sdata->local; 18875cf121c3SJohannes Berg struct ieee80211_tx_data tx; 188897b045d6SJohannes Berg ieee80211_tx_result res_prepare; 1889e039fa4aSJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 18907bb45683SJohannes Berg bool result = true; 189174e4dbfdSJohannes Berg int led_len; 1892e2ebc74dSJohannes Berg 1893e2ebc74dSJohannes Berg if (unlikely(skb->len < 10)) { 1894e2ebc74dSJohannes Berg dev_kfree_skb(skb); 18957bb45683SJohannes Berg return true; 1896e2ebc74dSJohannes Berg } 1897e2ebc74dSJohannes Berg 189858d4185eSJohannes Berg /* initialises tx */ 189974e4dbfdSJohannes Berg led_len = skb->len; 19007c10770fSJohannes Berg res_prepare = ieee80211_tx_prepare(sdata, &tx, sta, skb); 1901e2ebc74dSJohannes Berg 1902cd8ffc80SJohannes Berg if (unlikely(res_prepare == TX_DROP)) { 1903c3e7724bSFelix Fietkau ieee80211_free_txskb(&local->hw, skb); 190455de908aSJohannes Berg return true; 1905cd8ffc80SJohannes Berg } else if (unlikely(res_prepare == TX_QUEUED)) { 190655de908aSJohannes Berg return true; 1907e2ebc74dSJohannes Berg } 1908e2ebc74dSJohannes Berg 19093a25a8c8SJohannes Berg /* set up hw_queue value early */ 19103a25a8c8SJohannes Berg if (!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) || 191130686bf7SJohannes Berg !ieee80211_hw_check(&local->hw, QUEUE_CONTROL)) 19123a25a8c8SJohannes Berg info->hw_queue = 19133a25a8c8SJohannes Berg sdata->vif.hw_queue[skb_get_queue_mapping(skb)]; 19143a25a8c8SJohannes Berg 1915bb42f2d1SToke Høiland-Jørgensen if (invoke_tx_handlers_early(&tx)) 19166eae4a6cSBob Copeland return true; 1917bb42f2d1SToke Høiland-Jørgensen 1918bb42f2d1SToke Høiland-Jørgensen if (ieee80211_queue_skb(local, sdata, tx.sta, tx.skb)) 1919bb42f2d1SToke Høiland-Jørgensen return true; 1920bb42f2d1SToke Høiland-Jørgensen 1921bb42f2d1SToke Høiland-Jørgensen if (!invoke_tx_handlers_late(&tx)) 192274e4dbfdSJohannes Berg result = __ieee80211_tx(local, &tx.skbs, led_len, 192374e4dbfdSJohannes Berg tx.sta, txpending); 192455de908aSJohannes Berg 19257bb45683SJohannes Berg return result; 1926e2ebc74dSJohannes Berg } 1927e2ebc74dSJohannes Berg 1928e2ebc74dSJohannes Berg /* device xmit handlers */ 1929e2ebc74dSJohannes Berg 193014f46c1eSJohannes Berg enum ieee80211_encrypt { 193114f46c1eSJohannes Berg ENCRYPT_NO, 193214f46c1eSJohannes Berg ENCRYPT_MGMT, 193314f46c1eSJohannes Berg ENCRYPT_DATA, 193414f46c1eSJohannes Berg }; 193514f46c1eSJohannes Berg 19363bff1865SYogesh Ashok Powar static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata, 193723c0752aSJohannes Berg struct sk_buff *skb, 193814f46c1eSJohannes Berg int head_need, 193914f46c1eSJohannes Berg enum ieee80211_encrypt encrypt) 194023c0752aSJohannes Berg { 19413bff1865SYogesh Ashok Powar struct ieee80211_local *local = sdata->local; 19429d0f50b8SFelix Fietkau bool enc_tailroom; 194323c0752aSJohannes Berg int tail_need = 0; 194423c0752aSJohannes Berg 194514f46c1eSJohannes Berg enc_tailroom = encrypt == ENCRYPT_MGMT || 194614f46c1eSJohannes Berg (encrypt == ENCRYPT_DATA && 194714f46c1eSJohannes Berg sdata->crypto_tx_tailroom_needed_cnt); 19489d0f50b8SFelix Fietkau 19499d0f50b8SFelix Fietkau if (enc_tailroom) { 195023c0752aSJohannes Berg tail_need = IEEE80211_ENCRYPT_TAILROOM; 195123c0752aSJohannes Berg tail_need -= skb_tailroom(skb); 195223c0752aSJohannes Berg tail_need = max_t(int, tail_need, 0); 195323c0752aSJohannes Berg } 195423c0752aSJohannes Berg 1955c70f59a2SIdo Yariv if (skb_cloned(skb) && 195630686bf7SJohannes Berg (!ieee80211_hw_check(&local->hw, SUPPORTS_CLONED_SKBS) || 19579d0f50b8SFelix Fietkau !skb_clone_writable(skb, ETH_HLEN) || enc_tailroom)) 195823c0752aSJohannes Berg I802_DEBUG_INC(local->tx_expand_skb_head_cloned); 19594cd06a34SFelix Fietkau else if (head_need || tail_need) 196023c0752aSJohannes Berg I802_DEBUG_INC(local->tx_expand_skb_head); 19614cd06a34SFelix Fietkau else 19624cd06a34SFelix Fietkau return 0; 196323c0752aSJohannes Berg 196423c0752aSJohannes Berg if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) { 19650fb9a9ecSJoe Perches wiphy_debug(local->hw.wiphy, 19660fb9a9ecSJoe Perches "failed to reallocate TX buffer\n"); 196723c0752aSJohannes Berg return -ENOMEM; 196823c0752aSJohannes Berg } 196923c0752aSJohannes Berg 197023c0752aSJohannes Berg return 0; 197123c0752aSJohannes Berg } 197223c0752aSJohannes Berg 19737c10770fSJohannes Berg void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, 197408aca29aSMathy Vanhoef struct sta_info *sta, struct sk_buff *skb) 1975e2ebc74dSJohannes Berg { 19763b8d81e0SJohannes Berg struct ieee80211_local *local = sdata->local; 1977e039fa4aSJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 197814f46c1eSJohannes Berg struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 1979e2ebc74dSJohannes Berg int headroom; 198014f46c1eSJohannes Berg enum ieee80211_encrypt encrypt; 1981e2ebc74dSJohannes Berg 198214f46c1eSJohannes Berg if (info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT) 198314f46c1eSJohannes Berg encrypt = ENCRYPT_NO; 198414f46c1eSJohannes Berg else if (ieee80211_is_mgmt(hdr->frame_control)) 198514f46c1eSJohannes Berg encrypt = ENCRYPT_MGMT; 198614f46c1eSJohannes Berg else 198714f46c1eSJohannes Berg encrypt = ENCRYPT_DATA; 198823c0752aSJohannes Berg 19893b8d81e0SJohannes Berg headroom = local->tx_headroom; 199014f46c1eSJohannes Berg if (encrypt != ENCRYPT_NO) 19912475b1ccSMax Stepanov headroom += sdata->encrypt_headroom; 199223c0752aSJohannes Berg headroom -= skb_headroom(skb); 199323c0752aSJohannes Berg headroom = max_t(int, 0, headroom); 199423c0752aSJohannes Berg 199514f46c1eSJohannes Berg if (ieee80211_skb_resize(sdata, skb, headroom, encrypt)) { 1996c3e7724bSFelix Fietkau ieee80211_free_txskb(&local->hw, skb); 19973b8d81e0SJohannes Berg return; 1998e2ebc74dSJohannes Berg } 1999e2ebc74dSJohannes Berg 200014f46c1eSJohannes Berg /* reload after potential resize */ 2001740c1aa3SSteve deRosier hdr = (struct ieee80211_hdr *) skb->data; 20025061b0c2SJohannes Berg info->control.vif = &sdata->vif; 2003cd8ffc80SJohannes Berg 20043f52b7e3SMarco Porsch if (ieee80211_vif_is_mesh(&sdata->vif)) { 20053f52b7e3SMarco Porsch if (ieee80211_is_data(hdr->frame_control) && 20063f52b7e3SMarco Porsch is_unicast_ether_addr(hdr->addr1)) { 2007bf7cd94dSJohannes Berg if (mesh_nexthop_resolve(sdata, skb)) 20083f52b7e3SMarco Porsch return; /* skb queued: don't free */ 20093f52b7e3SMarco Porsch } else { 20103f52b7e3SMarco Porsch ieee80211_mps_set_frame_flags(sdata, NULL, hdr); 20113f52b7e3SMarco Porsch } 2012cca89496SJavier Cardona } 2013cca89496SJavier Cardona 20142154c81cSJavier Cardona ieee80211_set_qos_hdr(sdata, skb); 201508aca29aSMathy Vanhoef ieee80211_tx(sdata, sta, skb, false); 2016e2ebc74dSJohannes Berg } 2017e2ebc74dSJohannes Berg 2018bddc0c41SMathy Vanhoef static bool ieee80211_validate_radiotap_len(struct sk_buff *skb) 201973b9f03aSJohannes Berg { 202073b9f03aSJohannes Berg struct ieee80211_radiotap_header *rthdr = 202173b9f03aSJohannes Berg (struct ieee80211_radiotap_header *)skb->data; 202273b9f03aSJohannes Berg 2023cb17ed29SMathy Vanhoef /* check for not even having the fixed radiotap header part */ 2024cb17ed29SMathy Vanhoef if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header))) 2025cb17ed29SMathy Vanhoef return false; /* too short to be possibly valid */ 2026cb17ed29SMathy Vanhoef 2027cb17ed29SMathy Vanhoef /* is it a header version we can trust to find length from? */ 2028cb17ed29SMathy Vanhoef if (unlikely(rthdr->it_version)) 2029cb17ed29SMathy Vanhoef return false; /* only version 0 is supported */ 2030cb17ed29SMathy Vanhoef 2031cb17ed29SMathy Vanhoef /* does the skb contain enough to deliver on the alleged length? */ 2032cb17ed29SMathy Vanhoef if (unlikely(skb->len < ieee80211_get_radiotap_len(skb->data))) 2033cb17ed29SMathy Vanhoef return false; /* skb too short for claimed rt header extent */ 2034cb17ed29SMathy Vanhoef 2035bddc0c41SMathy Vanhoef return true; 2036bddc0c41SMathy Vanhoef } 2037bddc0c41SMathy Vanhoef 2038bddc0c41SMathy Vanhoef bool ieee80211_parse_tx_radiotap(struct sk_buff *skb, 2039bddc0c41SMathy Vanhoef struct net_device *dev) 2040bddc0c41SMathy Vanhoef { 2041bddc0c41SMathy Vanhoef struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 2042bddc0c41SMathy Vanhoef struct ieee80211_radiotap_iterator iterator; 2043bddc0c41SMathy Vanhoef struct ieee80211_radiotap_header *rthdr = 2044bddc0c41SMathy Vanhoef (struct ieee80211_radiotap_header *) skb->data; 2045bddc0c41SMathy Vanhoef struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 2046bddc0c41SMathy Vanhoef int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len, 2047bddc0c41SMathy Vanhoef NULL); 2048bddc0c41SMathy Vanhoef u16 txflags; 2049bddc0c41SMathy Vanhoef u16 rate = 0; 2050bddc0c41SMathy Vanhoef bool rate_found = false; 2051bddc0c41SMathy Vanhoef u8 rate_retries = 0; 2052bddc0c41SMathy Vanhoef u16 rate_flags = 0; 2053bddc0c41SMathy Vanhoef u8 mcs_known, mcs_flags, mcs_bw; 2054bddc0c41SMathy Vanhoef u16 vht_known; 2055bddc0c41SMathy Vanhoef u8 vht_mcs = 0, vht_nss = 0; 2056bddc0c41SMathy Vanhoef int i; 2057bddc0c41SMathy Vanhoef 2058bddc0c41SMathy Vanhoef if (!ieee80211_validate_radiotap_len(skb)) 2059bddc0c41SMathy Vanhoef return false; 2060bddc0c41SMathy Vanhoef 206173b9f03aSJohannes Berg info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT | 206273b9f03aSJohannes Berg IEEE80211_TX_CTL_DONTFRAG; 206373b9f03aSJohannes Berg 206473b9f03aSJohannes Berg /* 206573b9f03aSJohannes Berg * for every radiotap entry that is present 206673b9f03aSJohannes Berg * (ieee80211_radiotap_iterator_next returns -ENOENT when no more 206773b9f03aSJohannes Berg * entries present, or -EINVAL on error) 206873b9f03aSJohannes Berg */ 206973b9f03aSJohannes Berg 207073b9f03aSJohannes Berg while (!ret) { 207173b9f03aSJohannes Berg ret = ieee80211_radiotap_iterator_next(&iterator); 207273b9f03aSJohannes Berg 207373b9f03aSJohannes Berg if (ret) 207473b9f03aSJohannes Berg continue; 207573b9f03aSJohannes Berg 207673b9f03aSJohannes Berg /* see if this argument is something we can use */ 207773b9f03aSJohannes Berg switch (iterator.this_arg_index) { 207873b9f03aSJohannes Berg /* 207973b9f03aSJohannes Berg * You must take care when dereferencing iterator.this_arg 208073b9f03aSJohannes Berg * for multibyte types... the pointer is not aligned. Use 208173b9f03aSJohannes Berg * get_unaligned((type *)iterator.this_arg) to dereference 208273b9f03aSJohannes Berg * iterator.this_arg for type "type" safely on all arches. 208373b9f03aSJohannes Berg */ 208473b9f03aSJohannes Berg case IEEE80211_RADIOTAP_FLAGS: 208573b9f03aSJohannes Berg if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) { 208673b9f03aSJohannes Berg /* 208773b9f03aSJohannes Berg * this indicates that the skb we have been 208873b9f03aSJohannes Berg * handed has the 32-bit FCS CRC at the end... 208973b9f03aSJohannes Berg * we should react to that by snipping it off 209073b9f03aSJohannes Berg * because it will be recomputed and added 209173b9f03aSJohannes Berg * on transmission 209273b9f03aSJohannes Berg */ 209373b9f03aSJohannes Berg if (skb->len < (iterator._max_length + FCS_LEN)) 209473b9f03aSJohannes Berg return false; 209573b9f03aSJohannes Berg 209673b9f03aSJohannes Berg skb_trim(skb, skb->len - FCS_LEN); 209773b9f03aSJohannes Berg } 209873b9f03aSJohannes Berg if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP) 209973b9f03aSJohannes Berg info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT; 210073b9f03aSJohannes Berg if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) 210173b9f03aSJohannes Berg info->flags &= ~IEEE80211_TX_CTL_DONTFRAG; 210273b9f03aSJohannes Berg break; 210373b9f03aSJohannes Berg 210473b9f03aSJohannes Berg case IEEE80211_RADIOTAP_TX_FLAGS: 210573b9f03aSJohannes Berg txflags = get_unaligned_le16(iterator.this_arg); 210673b9f03aSJohannes Berg if (txflags & IEEE80211_RADIOTAP_F_TX_NOACK) 210773b9f03aSJohannes Berg info->flags |= IEEE80211_TX_CTL_NO_ACK; 2108e02281e7SMathy Vanhoef if (txflags & IEEE80211_RADIOTAP_F_TX_NOSEQNO) 2109e02281e7SMathy Vanhoef info->control.flags |= IEEE80211_TX_CTRL_NO_SEQNO; 211030df8130SMathy Vanhoef if (txflags & IEEE80211_RADIOTAP_F_TX_ORDER) 211130df8130SMathy Vanhoef info->control.flags |= 211230df8130SMathy Vanhoef IEEE80211_TX_CTRL_DONT_REORDER; 211373b9f03aSJohannes Berg break; 211473b9f03aSJohannes Berg 2115dfdfc2beSSven Eckelmann case IEEE80211_RADIOTAP_RATE: 2116dfdfc2beSSven Eckelmann rate = *iterator.this_arg; 2117dfdfc2beSSven Eckelmann rate_flags = 0; 2118dfdfc2beSSven Eckelmann rate_found = true; 2119dfdfc2beSSven Eckelmann break; 2120dfdfc2beSSven Eckelmann 2121dfdfc2beSSven Eckelmann case IEEE80211_RADIOTAP_DATA_RETRIES: 2122dfdfc2beSSven Eckelmann rate_retries = *iterator.this_arg; 2123dfdfc2beSSven Eckelmann break; 2124dfdfc2beSSven Eckelmann 2125dfdfc2beSSven Eckelmann case IEEE80211_RADIOTAP_MCS: 2126dfdfc2beSSven Eckelmann mcs_known = iterator.this_arg[0]; 2127dfdfc2beSSven Eckelmann mcs_flags = iterator.this_arg[1]; 2128dfdfc2beSSven Eckelmann if (!(mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_MCS)) 2129dfdfc2beSSven Eckelmann break; 2130dfdfc2beSSven Eckelmann 2131dfdfc2beSSven Eckelmann rate_found = true; 2132dfdfc2beSSven Eckelmann rate = iterator.this_arg[2]; 2133dfdfc2beSSven Eckelmann rate_flags = IEEE80211_TX_RC_MCS; 2134dfdfc2beSSven Eckelmann 2135dfdfc2beSSven Eckelmann if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_GI && 2136dfdfc2beSSven Eckelmann mcs_flags & IEEE80211_RADIOTAP_MCS_SGI) 2137dfdfc2beSSven Eckelmann rate_flags |= IEEE80211_TX_RC_SHORT_GI; 2138dfdfc2beSSven Eckelmann 2139f66b60f6SSven Eckelmann mcs_bw = mcs_flags & IEEE80211_RADIOTAP_MCS_BW_MASK; 2140dfdfc2beSSven Eckelmann if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_BW && 2141f66b60f6SSven Eckelmann mcs_bw == IEEE80211_RADIOTAP_MCS_BW_40) 2142dfdfc2beSSven Eckelmann rate_flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; 2143f1864e19SPhilipp Borgers 2144f1864e19SPhilipp Borgers if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_FEC && 2145f1864e19SPhilipp Borgers mcs_flags & IEEE80211_RADIOTAP_MCS_FEC_LDPC) 2146f1864e19SPhilipp Borgers info->flags |= IEEE80211_TX_CTL_LDPC; 2147549fdd34SPhilipp Borgers 2148549fdd34SPhilipp Borgers if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_STBC) { 2149549fdd34SPhilipp Borgers u8 stbc = u8_get_bits(mcs_flags, 2150549fdd34SPhilipp Borgers IEEE80211_RADIOTAP_MCS_STBC_MASK); 2151549fdd34SPhilipp Borgers 2152549fdd34SPhilipp Borgers info->flags |= 2153549fdd34SPhilipp Borgers u32_encode_bits(stbc, 2154549fdd34SPhilipp Borgers IEEE80211_TX_CTL_STBC); 2155549fdd34SPhilipp Borgers } 2156dfdfc2beSSven Eckelmann break; 2157dfdfc2beSSven Eckelmann 2158646e76bbSLorenzo Bianconi case IEEE80211_RADIOTAP_VHT: 2159646e76bbSLorenzo Bianconi vht_known = get_unaligned_le16(iterator.this_arg); 2160646e76bbSLorenzo Bianconi rate_found = true; 2161646e76bbSLorenzo Bianconi 2162646e76bbSLorenzo Bianconi rate_flags = IEEE80211_TX_RC_VHT_MCS; 2163646e76bbSLorenzo Bianconi if ((vht_known & IEEE80211_RADIOTAP_VHT_KNOWN_GI) && 2164646e76bbSLorenzo Bianconi (iterator.this_arg[2] & 2165646e76bbSLorenzo Bianconi IEEE80211_RADIOTAP_VHT_FLAG_SGI)) 2166646e76bbSLorenzo Bianconi rate_flags |= IEEE80211_TX_RC_SHORT_GI; 2167646e76bbSLorenzo Bianconi if (vht_known & 2168646e76bbSLorenzo Bianconi IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH) { 2169646e76bbSLorenzo Bianconi if (iterator.this_arg[3] == 1) 2170646e76bbSLorenzo Bianconi rate_flags |= 2171646e76bbSLorenzo Bianconi IEEE80211_TX_RC_40_MHZ_WIDTH; 2172646e76bbSLorenzo Bianconi else if (iterator.this_arg[3] == 4) 2173646e76bbSLorenzo Bianconi rate_flags |= 2174646e76bbSLorenzo Bianconi IEEE80211_TX_RC_80_MHZ_WIDTH; 2175646e76bbSLorenzo Bianconi else if (iterator.this_arg[3] == 11) 2176646e76bbSLorenzo Bianconi rate_flags |= 2177646e76bbSLorenzo Bianconi IEEE80211_TX_RC_160_MHZ_WIDTH; 2178646e76bbSLorenzo Bianconi } 2179646e76bbSLorenzo Bianconi 2180646e76bbSLorenzo Bianconi vht_mcs = iterator.this_arg[4] >> 4; 2181646e76bbSLorenzo Bianconi vht_nss = iterator.this_arg[4] & 0xF; 2182646e76bbSLorenzo Bianconi break; 2183646e76bbSLorenzo Bianconi 218473b9f03aSJohannes Berg /* 218573b9f03aSJohannes Berg * Please update the file 2186429ff87bSMauro Carvalho Chehab * Documentation/networking/mac80211-injection.rst 218773b9f03aSJohannes Berg * when parsing new fields here. 218873b9f03aSJohannes Berg */ 218973b9f03aSJohannes Berg 219073b9f03aSJohannes Berg default: 219173b9f03aSJohannes Berg break; 219273b9f03aSJohannes Berg } 219373b9f03aSJohannes Berg } 219473b9f03aSJohannes Berg 219573b9f03aSJohannes Berg if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */ 219673b9f03aSJohannes Berg return false; 219773b9f03aSJohannes Berg 2198dfdfc2beSSven Eckelmann if (rate_found) { 2199bddc0c41SMathy Vanhoef struct ieee80211_supported_band *sband = 2200bddc0c41SMathy Vanhoef local->hw.wiphy->bands[info->band]; 2201bddc0c41SMathy Vanhoef 2202dfdfc2beSSven Eckelmann info->control.flags |= IEEE80211_TX_CTRL_RATE_INJECT; 2203dfdfc2beSSven Eckelmann 2204dfdfc2beSSven Eckelmann for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { 2205dfdfc2beSSven Eckelmann info->control.rates[i].idx = -1; 2206dfdfc2beSSven Eckelmann info->control.rates[i].flags = 0; 2207dfdfc2beSSven Eckelmann info->control.rates[i].count = 0; 2208dfdfc2beSSven Eckelmann } 2209dfdfc2beSSven Eckelmann 2210dfdfc2beSSven Eckelmann if (rate_flags & IEEE80211_TX_RC_MCS) { 2211dfdfc2beSSven Eckelmann info->control.rates[0].idx = rate; 2212646e76bbSLorenzo Bianconi } else if (rate_flags & IEEE80211_TX_RC_VHT_MCS) { 2213646e76bbSLorenzo Bianconi ieee80211_rate_set_vht(info->control.rates, vht_mcs, 2214646e76bbSLorenzo Bianconi vht_nss); 2215bddc0c41SMathy Vanhoef } else if (sband) { 2216dfdfc2beSSven Eckelmann for (i = 0; i < sband->n_bitrates; i++) { 2217dfdfc2beSSven Eckelmann if (rate * 5 != sband->bitrates[i].bitrate) 2218dfdfc2beSSven Eckelmann continue; 2219dfdfc2beSSven Eckelmann 2220dfdfc2beSSven Eckelmann info->control.rates[0].idx = i; 2221dfdfc2beSSven Eckelmann break; 2222dfdfc2beSSven Eckelmann } 2223dfdfc2beSSven Eckelmann } 2224dfdfc2beSSven Eckelmann 222507310a63SFelix Fietkau if (info->control.rates[0].idx < 0) 222607310a63SFelix Fietkau info->control.flags &= ~IEEE80211_TX_CTRL_RATE_INJECT; 222707310a63SFelix Fietkau 2228dfdfc2beSSven Eckelmann info->control.rates[0].flags = rate_flags; 2229dfdfc2beSSven Eckelmann info->control.rates[0].count = min_t(u8, rate_retries + 1, 2230dfdfc2beSSven Eckelmann local->hw.max_rate_tries); 2231dfdfc2beSSven Eckelmann } 2232dfdfc2beSSven Eckelmann 223373b9f03aSJohannes Berg return true; 223473b9f03aSJohannes Berg } 223573b9f03aSJohannes Berg 2236d0cf9c0dSStephen Hemminger netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, 2237e2ebc74dSJohannes Berg struct net_device *dev) 2238e2ebc74dSJohannes Berg { 2239e2ebc74dSJohannes Berg struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 224055de908aSJohannes Berg struct ieee80211_chanctx_conf *chanctx_conf; 22413b8d81e0SJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 2242f75f5c6fSHelmut Schaa struct ieee80211_hdr *hdr; 22435d9cf4a5SJohannes Berg struct ieee80211_sub_if_data *tmp_sdata, *sdata; 2244b4932836SJanusz Dziedzic struct cfg80211_chan_def *chandef; 22459b8a74e3SAndy Green u16 len_rthdr; 22465d9cf4a5SJohannes Berg int hdrlen; 2247e2ebc74dSJohannes Berg 2248cb17ed29SMathy Vanhoef memset(info, 0, sizeof(*info)); 2249cb17ed29SMathy Vanhoef info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS | 2250cb17ed29SMathy Vanhoef IEEE80211_TX_CTL_INJECTED; 22519b8a74e3SAndy Green 2252bddc0c41SMathy Vanhoef /* Sanity-check the length of the radiotap header */ 2253bddc0c41SMathy Vanhoef if (!ieee80211_validate_radiotap_len(skb)) 2254cb17ed29SMathy Vanhoef goto fail; 22559b8a74e3SAndy Green 2256cb17ed29SMathy Vanhoef /* we now know there is a radiotap header with a length we can use */ 22579b8a74e3SAndy Green len_rthdr = ieee80211_get_radiotap_len(skb->data); 22589b8a74e3SAndy Green 2259e2ebc74dSJohannes Berg /* 2260e2ebc74dSJohannes Berg * fix up the pointers accounting for the radiotap 2261e2ebc74dSJohannes Berg * header still being in there. We are being given 2262e2ebc74dSJohannes Berg * a precooked IEEE80211 header so no need for 2263e2ebc74dSJohannes Berg * normal processing 2264e2ebc74dSJohannes Berg */ 22659b8a74e3SAndy Green skb_set_mac_header(skb, len_rthdr); 2266e2ebc74dSJohannes Berg /* 22679b8a74e3SAndy Green * these are just fixed to the end of the rt area since we 22689b8a74e3SAndy Green * don't have any better information and at this point, nobody cares 2269e2ebc74dSJohannes Berg */ 22709b8a74e3SAndy Green skb_set_network_header(skb, len_rthdr); 22719b8a74e3SAndy Green skb_set_transport_header(skb, len_rthdr); 2272e2ebc74dSJohannes Berg 22735d9cf4a5SJohannes Berg if (skb->len < len_rthdr + 2) 22745d9cf4a5SJohannes Berg goto fail; 22755d9cf4a5SJohannes Berg 22765d9cf4a5SJohannes Berg hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr); 22775d9cf4a5SJohannes Berg hdrlen = ieee80211_hdrlen(hdr->frame_control); 22785d9cf4a5SJohannes Berg 22795d9cf4a5SJohannes Berg if (skb->len < len_rthdr + hdrlen) 22805d9cf4a5SJohannes Berg goto fail; 22815d9cf4a5SJohannes Berg 2282f75f5c6fSHelmut Schaa /* 2283f75f5c6fSHelmut Schaa * Initialize skb->protocol if the injected frame is a data frame 2284f75f5c6fSHelmut Schaa * carrying a rfc1042 header 2285f75f5c6fSHelmut Schaa */ 2286f75f5c6fSHelmut Schaa if (ieee80211_is_data(hdr->frame_control) && 22875d9cf4a5SJohannes Berg skb->len >= len_rthdr + hdrlen + sizeof(rfc1042_header) + 2) { 22885d9cf4a5SJohannes Berg u8 *payload = (u8 *)hdr + hdrlen; 22895d9cf4a5SJohannes Berg 2290b203ca39SJoe Perches if (ether_addr_equal(payload, rfc1042_header)) 2291f75f5c6fSHelmut Schaa skb->protocol = cpu_to_be16((payload[6] << 8) | 2292f75f5c6fSHelmut Schaa payload[7]); 2293f75f5c6fSHelmut Schaa } 2294f75f5c6fSHelmut Schaa 22955d9cf4a5SJohannes Berg rcu_read_lock(); 22965d9cf4a5SJohannes Berg 22975d9cf4a5SJohannes Berg /* 22985d9cf4a5SJohannes Berg * We process outgoing injected frames that have a local address 22995d9cf4a5SJohannes Berg * we handle as though they are non-injected frames. 23005d9cf4a5SJohannes Berg * This code here isn't entirely correct, the local MAC address 23015d9cf4a5SJohannes Berg * isn't always enough to find the interface to use; for proper 230270d9c599SJohannes Berg * VLAN support we have an nl80211-based mechanism. 2303b226a826SJohannes Berg * 2304b226a826SJohannes Berg * This is necessary, for example, for old hostapd versions that 2305b226a826SJohannes Berg * don't use nl80211-based management TX/RX. 23065d9cf4a5SJohannes Berg */ 23075d9cf4a5SJohannes Berg sdata = IEEE80211_DEV_TO_SUB_IF(dev); 23085d9cf4a5SJohannes Berg 23095d9cf4a5SJohannes Berg list_for_each_entry_rcu(tmp_sdata, &local->interfaces, list) { 23105d9cf4a5SJohannes Berg if (!ieee80211_sdata_running(tmp_sdata)) 23115d9cf4a5SJohannes Berg continue; 23125d9cf4a5SJohannes Berg if (tmp_sdata->vif.type == NL80211_IFTYPE_MONITOR || 231370d9c599SJohannes Berg tmp_sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 23145d9cf4a5SJohannes Berg continue; 2315b203ca39SJoe Perches if (ether_addr_equal(tmp_sdata->vif.addr, hdr->addr2)) { 23165d9cf4a5SJohannes Berg sdata = tmp_sdata; 23175d9cf4a5SJohannes Berg break; 23185d9cf4a5SJohannes Berg } 23195d9cf4a5SJohannes Berg } 23207351c6bdSJohannes Berg 232155de908aSJohannes Berg chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 232255de908aSJohannes Berg if (!chanctx_conf) { 232355de908aSJohannes Berg tmp_sdata = rcu_dereference(local->monitor_sdata); 232455de908aSJohannes Berg if (tmp_sdata) 232555de908aSJohannes Berg chanctx_conf = 232655de908aSJohannes Berg rcu_dereference(tmp_sdata->vif.chanctx_conf); 232755de908aSJohannes Berg } 232855de908aSJohannes Berg 2329b4a7ff75SFelix Fietkau if (chanctx_conf) 2330b4932836SJanusz Dziedzic chandef = &chanctx_conf->def; 2331b4a7ff75SFelix Fietkau else if (!local->use_chanctx) 2332b4932836SJanusz Dziedzic chandef = &local->_oper_chandef; 2333b4a7ff75SFelix Fietkau else 2334b4a7ff75SFelix Fietkau goto fail_rcu; 233555de908aSJohannes Berg 233655de908aSJohannes Berg /* 233755de908aSJohannes Berg * Frame injection is not allowed if beaconing is not allowed 233855de908aSJohannes Berg * or if we need radar detection. Beaconing is usually not allowed when 233955de908aSJohannes Berg * the mode or operation (Adhoc, AP, Mesh) does not support DFS. 234055de908aSJohannes Berg * Passive scan is also used in world regulatory domains where 234155de908aSJohannes Berg * your country is not known and as such it should be treated as 234255de908aSJohannes Berg * NO TX unless the channel is explicitly allowed in which case 234355de908aSJohannes Berg * your current regulatory domain would not have the passive scan 234455de908aSJohannes Berg * flag. 234555de908aSJohannes Berg * 234655de908aSJohannes Berg * Since AP mode uses monitor interfaces to inject/TX management 234755de908aSJohannes Berg * frames we can make AP mode the exception to this rule once it 234855de908aSJohannes Berg * supports radar detection as its implementation can deal with 234955de908aSJohannes Berg * radar detection by itself. We can do that later by adding a 235055de908aSJohannes Berg * monitor flag interfaces used for AP support. 235155de908aSJohannes Berg */ 2352b4932836SJanusz Dziedzic if (!cfg80211_reg_can_beacon(local->hw.wiphy, chandef, 2353b4932836SJanusz Dziedzic sdata->vif.type)) 235455de908aSJohannes Berg goto fail_rcu; 235555de908aSJohannes Berg 235673c4e195SJohannes Berg info->band = chandef->chan->band; 2357109843b0SLorenzo Bianconi 235896a7109aSJohan Almbladh /* Initialize skb->priority according to frame type and TID class, 235996a7109aSJohan Almbladh * with respect to the sub interface that the frame will actually 236096a7109aSJohan Almbladh * be transmitted on. If the DONT_REORDER flag is set, the original 236196a7109aSJohan Almbladh * skb-priority is preserved to assure frames injected with this 236296a7109aSJohan Almbladh * flag are not reordered relative to each other. 236396a7109aSJohan Almbladh */ 236496a7109aSJohan Almbladh ieee80211_select_queue_80211(sdata, skb, hdr); 236596a7109aSJohan Almbladh skb_set_queue_mapping(skb, ieee80211_ac_from_tid(skb->priority)); 236696a7109aSJohan Almbladh 2367bddc0c41SMathy Vanhoef /* 2368bddc0c41SMathy Vanhoef * Process the radiotap header. This will now take into account the 2369bddc0c41SMathy Vanhoef * selected chandef above to accurately set injection rates and 2370bddc0c41SMathy Vanhoef * retransmissions. 2371bddc0c41SMathy Vanhoef */ 2372bddc0c41SMathy Vanhoef if (!ieee80211_parse_tx_radiotap(skb, dev)) 2373bddc0c41SMathy Vanhoef goto fail_rcu; 2374bddc0c41SMathy Vanhoef 2375cb17ed29SMathy Vanhoef /* remove the injection radiotap header */ 2376cb17ed29SMathy Vanhoef skb_pull(skb, len_rthdr); 2377109843b0SLorenzo Bianconi 237808aca29aSMathy Vanhoef ieee80211_xmit(sdata, NULL, skb); 23795d9cf4a5SJohannes Berg rcu_read_unlock(); 23805d9cf4a5SJohannes Berg 2381e2ebc74dSJohannes Berg return NETDEV_TX_OK; 23829b8a74e3SAndy Green 238355de908aSJohannes Berg fail_rcu: 238455de908aSJohannes Berg rcu_read_unlock(); 23859b8a74e3SAndy Green fail: 23869b8a74e3SAndy Green dev_kfree_skb(skb); 23879b8a74e3SAndy Green return NETDEV_TX_OK; /* meaning, we dealt with the skb */ 2388e2ebc74dSJohannes Berg } 2389e2ebc74dSJohannes Berg 239097ffe757SJohannes Berg static inline bool ieee80211_is_tdls_setup(struct sk_buff *skb) 2391ad38bfc9SMatti Gottlieb { 239297ffe757SJohannes Berg u16 ethertype = (skb->data[12] << 8) | skb->data[13]; 2393ad38bfc9SMatti Gottlieb 239497ffe757SJohannes Berg return ethertype == ETH_P_TDLS && 239597ffe757SJohannes Berg skb->len > 14 && 239697ffe757SJohannes Berg skb->data[14] == WLAN_TDLS_SNAP_RFTYPE; 239797ffe757SJohannes Berg } 239897ffe757SJohannes Berg 239950ff477aSJohn Crispin int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata, 240097ffe757SJohannes Berg struct sk_buff *skb, 240197ffe757SJohannes Berg struct sta_info **sta_out) 240297ffe757SJohannes Berg { 240397ffe757SJohannes Berg struct sta_info *sta; 240497ffe757SJohannes Berg 240597ffe757SJohannes Berg switch (sdata->vif.type) { 240697ffe757SJohannes Berg case NL80211_IFTYPE_AP_VLAN: 240797ffe757SJohannes Berg sta = rcu_dereference(sdata->u.vlan.sta); 240897ffe757SJohannes Berg if (sta) { 240997ffe757SJohannes Berg *sta_out = sta; 241097ffe757SJohannes Berg return 0; 241197ffe757SJohannes Berg } else if (sdata->wdev.use_4addr) { 241297ffe757SJohannes Berg return -ENOLINK; 241397ffe757SJohannes Berg } 2414fc0561dcSGustavo A. R. Silva fallthrough; 241597ffe757SJohannes Berg case NL80211_IFTYPE_AP: 241697ffe757SJohannes Berg case NL80211_IFTYPE_OCB: 241797ffe757SJohannes Berg case NL80211_IFTYPE_ADHOC: 241897ffe757SJohannes Berg if (is_multicast_ether_addr(skb->data)) { 241997ffe757SJohannes Berg *sta_out = ERR_PTR(-ENOENT); 242097ffe757SJohannes Berg return 0; 242197ffe757SJohannes Berg } 242297ffe757SJohannes Berg sta = sta_info_get_bss(sdata, skb->data); 242397ffe757SJohannes Berg break; 242497ffe757SJohannes Berg #ifdef CONFIG_MAC80211_MESH 242597ffe757SJohannes Berg case NL80211_IFTYPE_MESH_POINT: 242697ffe757SJohannes Berg /* determined much later */ 242797ffe757SJohannes Berg *sta_out = NULL; 242897ffe757SJohannes Berg return 0; 242997ffe757SJohannes Berg #endif 243097ffe757SJohannes Berg case NL80211_IFTYPE_STATION: 243197ffe757SJohannes Berg if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) { 243297ffe757SJohannes Berg sta = sta_info_get(sdata, skb->data); 243311d62cafSJohannes Berg if (sta && test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { 243411d62cafSJohannes Berg if (test_sta_flag(sta, 243511d62cafSJohannes Berg WLAN_STA_TDLS_PEER_AUTH)) { 243697ffe757SJohannes Berg *sta_out = sta; 243797ffe757SJohannes Berg return 0; 243897ffe757SJohannes Berg } 243997ffe757SJohannes Berg 244097ffe757SJohannes Berg /* 244197ffe757SJohannes Berg * TDLS link during setup - throw out frames to 244297ffe757SJohannes Berg * peer. Allow TDLS-setup frames to unauthorized 244397ffe757SJohannes Berg * peers for the special case of a link teardown 244497ffe757SJohannes Berg * after a TDLS sta is removed due to being 244597ffe757SJohannes Berg * unreachable. 244697ffe757SJohannes Berg */ 244711d62cafSJohannes Berg if (!ieee80211_is_tdls_setup(skb)) 244897ffe757SJohannes Berg return -EINVAL; 244997ffe757SJohannes Berg } 245097ffe757SJohannes Berg 245197ffe757SJohannes Berg } 245297ffe757SJohannes Berg 245397ffe757SJohannes Berg sta = sta_info_get(sdata, sdata->u.mgd.bssid); 245497ffe757SJohannes Berg if (!sta) 245597ffe757SJohannes Berg return -ENOLINK; 245697ffe757SJohannes Berg break; 245797ffe757SJohannes Berg default: 245897ffe757SJohannes Berg return -EINVAL; 245997ffe757SJohannes Berg } 246097ffe757SJohannes Berg 246197ffe757SJohannes Berg *sta_out = sta ?: ERR_PTR(-ENOENT); 246297ffe757SJohannes Berg return 0; 2463ad38bfc9SMatti Gottlieb } 2464ad38bfc9SMatti Gottlieb 2465a7528198SMarkus Theil static u16 ieee80211_store_ack_skb(struct ieee80211_local *local, 24665d8983c8SJohn Crispin struct sk_buff *skb, 2467a7528198SMarkus Theil u32 *info_flags, 2468a7528198SMarkus Theil u64 *cookie) 24695d8983c8SJohn Crispin { 2470a7528198SMarkus Theil struct sk_buff *ack_skb; 24715d8983c8SJohn Crispin u16 info_id = 0; 24725d8983c8SJohn Crispin 2473a7528198SMarkus Theil if (skb->sk) 2474a7528198SMarkus Theil ack_skb = skb_clone_sk(skb); 2475a7528198SMarkus Theil else 2476a7528198SMarkus Theil ack_skb = skb_clone(skb, GFP_ATOMIC); 2477a7528198SMarkus Theil 24785d8983c8SJohn Crispin if (ack_skb) { 24795d8983c8SJohn Crispin unsigned long flags; 24805d8983c8SJohn Crispin int id; 24815d8983c8SJohn Crispin 24825d8983c8SJohn Crispin spin_lock_irqsave(&local->ack_status_lock, flags); 24835d8983c8SJohn Crispin id = idr_alloc(&local->ack_status_frames, ack_skb, 2484f2b18bacSJohannes Berg 1, 0x2000, GFP_ATOMIC); 24855d8983c8SJohn Crispin spin_unlock_irqrestore(&local->ack_status_lock, flags); 24865d8983c8SJohn Crispin 24875d8983c8SJohn Crispin if (id >= 0) { 24885d8983c8SJohn Crispin info_id = id; 24895d8983c8SJohn Crispin *info_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; 2490a7528198SMarkus Theil if (cookie) { 2491a7528198SMarkus Theil *cookie = ieee80211_mgmt_tx_cookie(local); 2492a7528198SMarkus Theil IEEE80211_SKB_CB(ack_skb)->ack.cookie = *cookie; 2493a7528198SMarkus Theil } 24945d8983c8SJohn Crispin } else { 24955d8983c8SJohn Crispin kfree_skb(ack_skb); 24965d8983c8SJohn Crispin } 24975d8983c8SJohn Crispin } 24985d8983c8SJohn Crispin 24995d8983c8SJohn Crispin return info_id; 25005d8983c8SJohn Crispin } 25015d8983c8SJohn Crispin 2502e2ebc74dSJohannes Berg /** 25034c9451edSJohannes Berg * ieee80211_build_hdr - build 802.11 header in the given frame 25044c9451edSJohannes Berg * @sdata: virtual interface to build the header for 25054c9451edSJohannes Berg * @skb: the skb to build the header in 250624d342c5SLiad Kaufman * @info_flags: skb flags to set 2507f0daf54fSJohannes Berg * @sta: the station pointer 250806016772SRajkumar Manoharan * @ctrl_flags: info control flags to set 2509f0daf54fSJohannes Berg * @cookie: cookie pointer to fill (if not %NULL) 2510e2ebc74dSJohannes Berg * 25114c9451edSJohannes Berg * This function takes the skb with 802.3 header and reformats the header to 25124c9451edSJohannes Berg * the appropriate IEEE 802.11 header based on which interface the packet is 25134c9451edSJohannes Berg * being transmitted on. 2514e2ebc74dSJohannes Berg * 25154c9451edSJohannes Berg * Note that this function also takes care of the TX status request and 25164c9451edSJohannes Berg * potential unsharing of the SKB - this needs to be interleaved with the 25174c9451edSJohannes Berg * header building. 25184c9451edSJohannes Berg * 25194c9451edSJohannes Berg * The function requires the read-side RCU lock held 25204c9451edSJohannes Berg * 25214c9451edSJohannes Berg * Returns: the (possibly reallocated) skb or an ERR_PTR() code 2522e2ebc74dSJohannes Berg */ 25234c9451edSJohannes Berg static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata, 25247c10770fSJohannes Berg struct sk_buff *skb, u32 info_flags, 2525a7528198SMarkus Theil struct sta_info *sta, u32 ctrl_flags, 2526a7528198SMarkus Theil u64 *cookie) 2527e2ebc74dSJohannes Berg { 2528133b8226SJohannes Berg struct ieee80211_local *local = sdata->local; 2529489ee919SFelix Fietkau struct ieee80211_tx_info *info; 2530dcf33963SJohannes Berg int head_need; 2531065e9605SHarvey Harrison u16 ethertype, hdrlen, meshhdrlen = 0; 2532065e9605SHarvey Harrison __le16 fc; 2533e2ebc74dSJohannes Berg struct ieee80211_hdr hdr; 2534ff67bb86SWey-Yi Guy struct ieee80211s_hdr mesh_hdr __maybe_unused; 2535b8bacc18SChun-Yeow Yeoh struct mesh_path __maybe_unused *mppath = NULL, *mpath = NULL; 2536e2ebc74dSJohannes Berg const u8 *encaps_data; 2537e2ebc74dSJohannes Berg int encaps_len, skip_header_bytes; 253897ffe757SJohannes Berg bool wme_sta = false, authorized = false; 253997ffe757SJohannes Berg bool tdls_peer; 2540a729cff8SJohannes Berg bool multicast; 2541a729cff8SJohannes Berg u16 info_id = 0; 254255de908aSJohannes Berg struct ieee80211_chanctx_conf *chanctx_conf; 254355de908aSJohannes Berg struct ieee80211_sub_if_data *ap_sdata; 254457fbcce3SJohannes Berg enum nl80211_band band; 25454c9451edSJohannes Berg int ret; 2546e2ebc74dSJohannes Berg 254797ffe757SJohannes Berg if (IS_ERR(sta)) 254897ffe757SJohannes Berg sta = NULL; 254997ffe757SJohannes Berg 2550276d9e82SJulius Niedworok #ifdef CONFIG_MAC80211_DEBUGFS 2551276d9e82SJulius Niedworok if (local->force_tx_status) 2552276d9e82SJulius Niedworok info_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; 2553276d9e82SJulius Niedworok #endif 2554276d9e82SJulius Niedworok 2555e2ebc74dSJohannes Berg /* convert Ethernet header to proper 802.11 header (based on 2556e2ebc74dSJohannes Berg * operation mode) */ 2557e2ebc74dSJohannes Berg ethertype = (skb->data[12] << 8) | skb->data[13]; 2558065e9605SHarvey Harrison fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); 2559e2ebc74dSJohannes Berg 256051fb61e7SJohannes Berg switch (sdata->vif.type) { 256105c914feSJohannes Berg case NL80211_IFTYPE_AP_VLAN: 256297ffe757SJohannes Berg if (sdata->wdev.use_4addr) { 2563f14543eeSFelix Fietkau fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); 2564f14543eeSFelix Fietkau /* RA TA DA SA */ 2565f14543eeSFelix Fietkau memcpy(hdr.addr1, sta->sta.addr, ETH_ALEN); 256647846c9bSJohannes Berg memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); 2567f14543eeSFelix Fietkau memcpy(hdr.addr3, skb->data, ETH_ALEN); 2568f14543eeSFelix Fietkau memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); 2569f14543eeSFelix Fietkau hdrlen = 30; 2570c2c98fdeSJohannes Berg authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); 2571a74a8c84SJohannes Berg wme_sta = sta->sta.wme; 2572f14543eeSFelix Fietkau } 257355de908aSJohannes Berg ap_sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, 257455de908aSJohannes Berg u.ap); 257555de908aSJohannes Berg chanctx_conf = rcu_dereference(ap_sdata->vif.chanctx_conf); 25764c9451edSJohannes Berg if (!chanctx_conf) { 25774c9451edSJohannes Berg ret = -ENOTCONN; 25784c9451edSJohannes Berg goto free; 25794c9451edSJohannes Berg } 25804bf88530SJohannes Berg band = chanctx_conf->def.chan->band; 258197ffe757SJohannes Berg if (sdata->wdev.use_4addr) 2582f14543eeSFelix Fietkau break; 2583fc0561dcSGustavo A. R. Silva fallthrough; 2584f14543eeSFelix Fietkau case NL80211_IFTYPE_AP: 2585fe80123dSArnd Bergmann if (sdata->vif.type == NL80211_IFTYPE_AP) 2586fe80123dSArnd Bergmann chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 25874c9451edSJohannes Berg if (!chanctx_conf) { 25884c9451edSJohannes Berg ret = -ENOTCONN; 25894c9451edSJohannes Berg goto free; 25904c9451edSJohannes Berg } 2591065e9605SHarvey Harrison fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); 2592e2ebc74dSJohannes Berg /* DA BSSID SA */ 2593e2ebc74dSJohannes Berg memcpy(hdr.addr1, skb->data, ETH_ALEN); 259447846c9bSJohannes Berg memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); 2595e2ebc74dSJohannes Berg memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN); 2596e2ebc74dSJohannes Berg hdrlen = 24; 25974bf88530SJohannes Berg band = chanctx_conf->def.chan->band; 2598cf966838SJohannes Berg break; 259933b64eb2SLuis Carlos Cobo #ifdef CONFIG_MAC80211_MESH 260005c914feSJohannes Berg case NL80211_IFTYPE_MESH_POINT: 2601b8bacc18SChun-Yeow Yeoh if (!is_multicast_ether_addr(skb->data)) { 2602163df6cfSChun-Yeow Yeoh struct sta_info *next_hop; 2603163df6cfSChun-Yeow Yeoh bool mpp_lookup = true; 2604163df6cfSChun-Yeow Yeoh 2605bf7cd94dSJohannes Berg mpath = mesh_path_lookup(sdata, skb->data); 2606163df6cfSChun-Yeow Yeoh if (mpath) { 2607163df6cfSChun-Yeow Yeoh mpp_lookup = false; 2608163df6cfSChun-Yeow Yeoh next_hop = rcu_dereference(mpath->next_hop); 2609163df6cfSChun-Yeow Yeoh if (!next_hop || 2610163df6cfSChun-Yeow Yeoh !(mpath->flags & (MESH_PATH_ACTIVE | 2611163df6cfSChun-Yeow Yeoh MESH_PATH_RESOLVING))) 2612163df6cfSChun-Yeow Yeoh mpp_lookup = true; 2613163df6cfSChun-Yeow Yeoh } 2614163df6cfSChun-Yeow Yeoh 2615ab1c7906SHenning Rogge if (mpp_lookup) { 2616bf7cd94dSJohannes Berg mppath = mpp_path_lookup(sdata, skb->data); 2617ab1c7906SHenning Rogge if (mppath) 2618ab1c7906SHenning Rogge mppath->exp_time = jiffies; 2619ab1c7906SHenning Rogge } 2620163df6cfSChun-Yeow Yeoh 2621163df6cfSChun-Yeow Yeoh if (mppath && mpath) 26222bdaf386SBob Copeland mesh_path_del(sdata, mpath->dst); 2623b8bacc18SChun-Yeow Yeoh } 262479617deeSYanBo 2625f76b57b4SJoel A Fernandes /* 26269d52501bSJoel A Fernandes * Use address extension if it is a packet from 26279d52501bSJoel A Fernandes * another interface or if we know the destination 26289d52501bSJoel A Fernandes * is being proxied by a portal (i.e. portal address 26299d52501bSJoel A Fernandes * differs from proxied address) 2630f76b57b4SJoel A Fernandes */ 2631b203ca39SJoe Perches if (ether_addr_equal(sdata->vif.addr, skb->data + ETH_ALEN) && 2632b203ca39SJoe Perches !(mppath && !ether_addr_equal(mppath->mpp, skb->data))) { 26333c5772a5SJavier Cardona hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, 26343c5772a5SJavier Cardona skb->data, skb->data + ETH_ALEN); 2635bf7cd94dSJohannes Berg meshhdrlen = ieee80211_new_mesh_header(sdata, &mesh_hdr, 2636bf7cd94dSJohannes Berg NULL, NULL); 263779617deeSYanBo } else { 263827f01124SThomas Pedersen /* DS -> MBSS (802.11-2012 13.11.3.3). 263927f01124SThomas Pedersen * For unicast with unknown forwarding information, 264027f01124SThomas Pedersen * destination might be in the MBSS or if that fails 264127f01124SThomas Pedersen * forwarded to another mesh gate. In either case 264227f01124SThomas Pedersen * resolution will be handled in ieee80211_xmit(), so 264327f01124SThomas Pedersen * leave the original DA. This also works for mcast */ 264427f01124SThomas Pedersen const u8 *mesh_da = skb->data; 264579617deeSYanBo 264627f01124SThomas Pedersen if (mppath) 26473c5772a5SJavier Cardona mesh_da = mppath->mpp; 264827f01124SThomas Pedersen else if (mpath) 26497c41f315SChun-Yeow Yeoh mesh_da = mpath->dst; 265027f01124SThomas Pedersen 26513c5772a5SJavier Cardona hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, 265247846c9bSJohannes Berg mesh_da, sdata->vif.addr); 265327f01124SThomas Pedersen if (is_multicast_ether_addr(mesh_da)) 265427f01124SThomas Pedersen /* DA TA mSA AE:SA */ 2655bf7cd94dSJohannes Berg meshhdrlen = ieee80211_new_mesh_header( 2656bf7cd94dSJohannes Berg sdata, &mesh_hdr, 2657bf7cd94dSJohannes Berg skb->data + ETH_ALEN, NULL); 26583c5772a5SJavier Cardona else 265927f01124SThomas Pedersen /* RA TA mDA mSA AE:DA SA */ 2660bf7cd94dSJohannes Berg meshhdrlen = ieee80211_new_mesh_header( 2661bf7cd94dSJohannes Berg sdata, &mesh_hdr, skb->data, 26623c5772a5SJavier Cardona skb->data + ETH_ALEN); 266379617deeSYanBo 266479617deeSYanBo } 266555de908aSJohannes Berg chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 26664c9451edSJohannes Berg if (!chanctx_conf) { 26674c9451edSJohannes Berg ret = -ENOTCONN; 26684c9451edSJohannes Berg goto free; 26694c9451edSJohannes Berg } 26704bf88530SJohannes Berg band = chanctx_conf->def.chan->band; 26718828f81aSRajkumar Manoharan 26728828f81aSRajkumar Manoharan /* For injected frames, fill RA right away as nexthop lookup 26738828f81aSRajkumar Manoharan * will be skipped. 26748828f81aSRajkumar Manoharan */ 26758828f81aSRajkumar Manoharan if ((ctrl_flags & IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP) && 26768828f81aSRajkumar Manoharan is_zero_ether_addr(hdr.addr1)) 26778828f81aSRajkumar Manoharan memcpy(hdr.addr1, skb->data, ETH_ALEN); 267833b64eb2SLuis Carlos Cobo break; 267933b64eb2SLuis Carlos Cobo #endif 268005c914feSJohannes Berg case NL80211_IFTYPE_STATION: 268197ffe757SJohannes Berg /* we already did checks when looking up the RA STA */ 268297ffe757SJohannes Berg tdls_peer = test_sta_flag(sta, WLAN_STA_TDLS_PEER); 2683941c93cdSArik Nemtsov 268497ffe757SJohannes Berg if (tdls_peer) { 2685941c93cdSArik Nemtsov /* DA SA BSSID */ 2686941c93cdSArik Nemtsov memcpy(hdr.addr1, skb->data, ETH_ALEN); 2687941c93cdSArik Nemtsov memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); 2688941c93cdSArik Nemtsov memcpy(hdr.addr3, sdata->u.mgd.bssid, ETH_ALEN); 2689941c93cdSArik Nemtsov hdrlen = 24; 2690941c93cdSArik Nemtsov } else if (sdata->u.mgd.use_4addr && 2691a621fa4dSJohannes Berg cpu_to_be16(ethertype) != sdata->control_port_protocol) { 2692941c93cdSArik Nemtsov fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | 2693941c93cdSArik Nemtsov IEEE80211_FCTL_TODS); 2694f14543eeSFelix Fietkau /* RA TA DA SA */ 2695941c93cdSArik Nemtsov memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN); 269647846c9bSJohannes Berg memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); 2697f14543eeSFelix Fietkau memcpy(hdr.addr3, skb->data, ETH_ALEN); 2698f14543eeSFelix Fietkau memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); 2699f14543eeSFelix Fietkau hdrlen = 30; 2700f14543eeSFelix Fietkau } else { 2701065e9605SHarvey Harrison fc |= cpu_to_le16(IEEE80211_FCTL_TODS); 2702e2ebc74dSJohannes Berg /* BSSID SA DA */ 2703941c93cdSArik Nemtsov memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN); 2704e2ebc74dSJohannes Berg memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); 2705e2ebc74dSJohannes Berg memcpy(hdr.addr3, skb->data, ETH_ALEN); 2706e2ebc74dSJohannes Berg hdrlen = 24; 2707f14543eeSFelix Fietkau } 270855de908aSJohannes Berg chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 27094c9451edSJohannes Berg if (!chanctx_conf) { 27104c9451edSJohannes Berg ret = -ENOTCONN; 27114c9451edSJohannes Berg goto free; 27124c9451edSJohannes Berg } 27134bf88530SJohannes Berg band = chanctx_conf->def.chan->band; 2714cf966838SJohannes Berg break; 2715239281f8SRostislav Lisovy case NL80211_IFTYPE_OCB: 2716239281f8SRostislav Lisovy /* DA SA BSSID */ 2717239281f8SRostislav Lisovy memcpy(hdr.addr1, skb->data, ETH_ALEN); 2718239281f8SRostislav Lisovy memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); 2719239281f8SRostislav Lisovy eth_broadcast_addr(hdr.addr3); 2720239281f8SRostislav Lisovy hdrlen = 24; 2721239281f8SRostislav Lisovy chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 27224c9451edSJohannes Berg if (!chanctx_conf) { 27234c9451edSJohannes Berg ret = -ENOTCONN; 27244c9451edSJohannes Berg goto free; 27254c9451edSJohannes Berg } 2726239281f8SRostislav Lisovy band = chanctx_conf->def.chan->band; 2727239281f8SRostislav Lisovy break; 272805c914feSJohannes Berg case NL80211_IFTYPE_ADHOC: 2729e2ebc74dSJohannes Berg /* DA SA BSSID */ 2730e2ebc74dSJohannes Berg memcpy(hdr.addr1, skb->data, ETH_ALEN); 2731e2ebc74dSJohannes Berg memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); 273246900298SJohannes Berg memcpy(hdr.addr3, sdata->u.ibss.bssid, ETH_ALEN); 2733e2ebc74dSJohannes Berg hdrlen = 24; 273455de908aSJohannes Berg chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 27354c9451edSJohannes Berg if (!chanctx_conf) { 27364c9451edSJohannes Berg ret = -ENOTCONN; 27374c9451edSJohannes Berg goto free; 27384c9451edSJohannes Berg } 27394bf88530SJohannes Berg band = chanctx_conf->def.chan->band; 2740cf966838SJohannes Berg break; 2741cf966838SJohannes Berg default: 27424c9451edSJohannes Berg ret = -EINVAL; 27434c9451edSJohannes Berg goto free; 2744e2ebc74dSJohannes Berg } 2745e2ebc74dSJohannes Berg 2746a729cff8SJohannes Berg multicast = is_multicast_ether_addr(hdr.addr1); 274797ffe757SJohannes Berg 274897ffe757SJohannes Berg /* sta is always NULL for mesh */ 2749c2c98fdeSJohannes Berg if (sta) { 2750c2c98fdeSJohannes Berg authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); 2751a74a8c84SJohannes Berg wme_sta = sta->sta.wme; 275297ffe757SJohannes Berg } else if (ieee80211_vif_is_mesh(&sdata->vif)) { 27534777be41SJavier Cardona /* For mesh, the use of the QoS header is mandatory */ 2754c2c98fdeSJohannes Berg wme_sta = true; 275597ffe757SJohannes Berg } 27564777be41SJavier Cardona 2757527871d7SJohannes Berg /* receiver does QoS (which also means we do) use it */ 2758527871d7SJohannes Berg if (wme_sta) { 2759065e9605SHarvey Harrison fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA); 2760e2ebc74dSJohannes Berg hdrlen += 2; 2761e2ebc74dSJohannes Berg } 2762ce3edf6dSJohannes Berg 2763ce3edf6dSJohannes Berg /* 2764238814fdSJohannes Berg * Drop unicast frames to unauthorised stations unless they are 2765238814fdSJohannes Berg * EAPOL frames from the local station. 2766ce3edf6dSJohannes Berg */ 276755182e4aSJohannes Berg if (unlikely(!ieee80211_vif_is_mesh(&sdata->vif) && 2768239281f8SRostislav Lisovy (sdata->vif.type != NL80211_IFTYPE_OCB) && 2769a6ececf4SSergey Ryazanov !multicast && !authorized && 277055182e4aSJohannes Berg (cpu_to_be16(ethertype) != sdata->control_port_protocol || 2771b203ca39SJoe Perches !ether_addr_equal(sdata->vif.addr, skb->data + ETH_ALEN)))) { 2772ce3edf6dSJohannes Berg #ifdef CONFIG_MAC80211_VERBOSE_DEBUG 2773bdcbd8e0SJohannes Berg net_info_ratelimited("%s: dropped frame to %pM (unauthorized port)\n", 27744c9451edSJohannes Berg sdata->name, hdr.addr1); 2775ce3edf6dSJohannes Berg #endif 2776ce3edf6dSJohannes Berg 2777ce3edf6dSJohannes Berg I802_DEBUG_INC(local->tx_handlers_drop_unauth_port); 2778ce3edf6dSJohannes Berg 27794c9451edSJohannes Berg ret = -EPERM; 27804c9451edSJohannes Berg goto free; 2781e2ebc74dSJohannes Berg } 2782e2ebc74dSJohannes Berg 2783a7528198SMarkus Theil if (unlikely(!multicast && ((skb->sk && 2784a7528198SMarkus Theil skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS) || 2785a7528198SMarkus Theil ctrl_flags & IEEE80211_TX_CTL_REQ_TX_STATUS))) 2786a7528198SMarkus Theil info_id = ieee80211_store_ack_skb(local, skb, &info_flags, 2787a7528198SMarkus Theil cookie); 2788a729cff8SJohannes Berg 27897e244707SHelmut Schaa /* 27907e244707SHelmut Schaa * If the skb is shared we need to obtain our own copy. 27917e244707SHelmut Schaa */ 27927e244707SHelmut Schaa if (skb_shared(skb)) { 2793a729cff8SJohannes Berg struct sk_buff *tmp_skb = skb; 2794a729cff8SJohannes Berg 2795a729cff8SJohannes Berg /* can't happen -- skb is a clone if info_id != 0 */ 2796a729cff8SJohannes Berg WARN_ON(info_id); 2797a729cff8SJohannes Berg 2798f8a0a781SFelix Fietkau skb = skb_clone(skb, GFP_ATOMIC); 27997e244707SHelmut Schaa kfree_skb(tmp_skb); 28007e244707SHelmut Schaa 28014c9451edSJohannes Berg if (!skb) { 28024c9451edSJohannes Berg ret = -ENOMEM; 28034c9451edSJohannes Berg goto free; 28044c9451edSJohannes Berg } 28057e244707SHelmut Schaa } 28067e244707SHelmut Schaa 2807065e9605SHarvey Harrison hdr.frame_control = fc; 2808e2ebc74dSJohannes Berg hdr.duration_id = 0; 2809e2ebc74dSJohannes Berg hdr.seq_ctrl = 0; 2810e2ebc74dSJohannes Berg 2811e2ebc74dSJohannes Berg skip_header_bytes = ETH_HLEN; 2812e2ebc74dSJohannes Berg if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) { 2813e2ebc74dSJohannes Berg encaps_data = bridge_tunnel_header; 2814e2ebc74dSJohannes Berg encaps_len = sizeof(bridge_tunnel_header); 2815e2ebc74dSJohannes Berg skip_header_bytes -= 2; 2816e5c5d22eSSimon Horman } else if (ethertype >= ETH_P_802_3_MIN) { 2817e2ebc74dSJohannes Berg encaps_data = rfc1042_header; 2818e2ebc74dSJohannes Berg encaps_len = sizeof(rfc1042_header); 2819e2ebc74dSJohannes Berg skip_header_bytes -= 2; 2820e2ebc74dSJohannes Berg } else { 2821e2ebc74dSJohannes Berg encaps_data = NULL; 2822e2ebc74dSJohannes Berg encaps_len = 0; 2823e2ebc74dSJohannes Berg } 2824e2ebc74dSJohannes Berg 2825e2ebc74dSJohannes Berg skb_pull(skb, skip_header_bytes); 282623c0752aSJohannes Berg head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb); 2827e2ebc74dSJohannes Berg 282823c0752aSJohannes Berg /* 282923c0752aSJohannes Berg * So we need to modify the skb header and hence need a copy of 283023c0752aSJohannes Berg * that. The head_need variable above doesn't, so far, include 283123c0752aSJohannes Berg * the needed header space that we don't need right away. If we 283223c0752aSJohannes Berg * can, then we don't reallocate right now but only after the 283323c0752aSJohannes Berg * frame arrives at the master device (if it does...) 283423c0752aSJohannes Berg * 283523c0752aSJohannes Berg * If we cannot, however, then we will reallocate to include all 283623c0752aSJohannes Berg * the ever needed space. Also, if we need to reallocate it anyway, 283723c0752aSJohannes Berg * make it big enough for everything we may ever need. 283823c0752aSJohannes Berg */ 2839e2ebc74dSJohannes Berg 28403a5be7d4SDavid S. Miller if (head_need > 0 || skb_cloned(skb)) { 28412475b1ccSMax Stepanov head_need += sdata->encrypt_headroom; 284223c0752aSJohannes Berg head_need += local->tx_headroom; 284323c0752aSJohannes Berg head_need = max_t(int, 0, head_need); 284414f46c1eSJohannes Berg if (ieee80211_skb_resize(sdata, skb, head_need, ENCRYPT_DATA)) { 2845c3e7724bSFelix Fietkau ieee80211_free_txskb(&local->hw, skb); 28461c963becSJohannes Berg skb = NULL; 28474c9451edSJohannes Berg return ERR_PTR(-ENOMEM); 2848c3e7724bSFelix Fietkau } 2849e2ebc74dSJohannes Berg } 2850e2ebc74dSJohannes Berg 2851eae4430eSFelix Fietkau if (encaps_data) 2852e2ebc74dSJohannes Berg memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len); 2853c29b9b9bSJohannes Berg 2854e4ab7eb0SYuri Ershov #ifdef CONFIG_MAC80211_MESH 2855eae4430eSFelix Fietkau if (meshhdrlen > 0) 285633b64eb2SLuis Carlos Cobo memcpy(skb_push(skb, meshhdrlen), &mesh_hdr, meshhdrlen); 2857e4ab7eb0SYuri Ershov #endif 285833b64eb2SLuis Carlos Cobo 2859065e9605SHarvey Harrison if (ieee80211_is_data_qos(fc)) { 2860c29b9b9bSJohannes Berg __le16 *qos_control; 2861c29b9b9bSJohannes Berg 2862d58ff351SJohannes Berg qos_control = skb_push(skb, 2); 2863c29b9b9bSJohannes Berg memcpy(skb_push(skb, hdrlen - 2), &hdr, hdrlen - 2); 2864c29b9b9bSJohannes Berg /* 2865c29b9b9bSJohannes Berg * Maybe we could actually set some fields here, for now just 2866c29b9b9bSJohannes Berg * initialise to zero to indicate no special operation. 2867c29b9b9bSJohannes Berg */ 2868c29b9b9bSJohannes Berg *qos_control = 0; 2869c29b9b9bSJohannes Berg } else 2870e2ebc74dSJohannes Berg memcpy(skb_push(skb, hdrlen), &hdr, hdrlen); 2871c29b9b9bSJohannes Berg 2872d57a544dSZhang Shengju skb_reset_mac_header(skb); 2873e2ebc74dSJohannes Berg 2874489ee919SFelix Fietkau info = IEEE80211_SKB_CB(skb); 28753b8d81e0SJohannes Berg memset(info, 0, sizeof(*info)); 28763b8d81e0SJohannes Berg 2877a729cff8SJohannes Berg info->flags = info_flags; 2878a729cff8SJohannes Berg info->ack_frame_id = info_id; 287973c4e195SJohannes Berg info->band = band; 288006016772SRajkumar Manoharan info->control.flags = ctrl_flags; 2881a729cff8SJohannes Berg 28824c9451edSJohannes Berg return skb; 28834c9451edSJohannes Berg free: 28844c9451edSJohannes Berg kfree_skb(skb); 28854c9451edSJohannes Berg return ERR_PTR(ret); 2886e2ebc74dSJohannes Berg } 2887e2ebc74dSJohannes Berg 288817c18bf8SJohannes Berg /* 288917c18bf8SJohannes Berg * fast-xmit overview 289017c18bf8SJohannes Berg * 289117c18bf8SJohannes Berg * The core idea of this fast-xmit is to remove per-packet checks by checking 289217c18bf8SJohannes Berg * them out of band. ieee80211_check_fast_xmit() implements the out-of-band 289317c18bf8SJohannes Berg * checks that are needed to get the sta->fast_tx pointer assigned, after which 289417c18bf8SJohannes Berg * much less work can be done per packet. For example, fragmentation must be 289517c18bf8SJohannes Berg * disabled or the fast_tx pointer will not be set. All the conditions are seen 289617c18bf8SJohannes Berg * in the code here. 289717c18bf8SJohannes Berg * 289817c18bf8SJohannes Berg * Once assigned, the fast_tx data structure also caches the per-packet 802.11 289917c18bf8SJohannes Berg * header and other data to aid packet processing in ieee80211_xmit_fast(). 290017c18bf8SJohannes Berg * 290117c18bf8SJohannes Berg * The most difficult part of this is that when any of these assumptions 290217c18bf8SJohannes Berg * change, an external trigger (i.e. a call to ieee80211_clear_fast_xmit(), 290317c18bf8SJohannes Berg * ieee80211_check_fast_xmit() or friends) is required to reset the data, 290417c18bf8SJohannes Berg * since the per-packet code no longer checks the conditions. This is reflected 290517c18bf8SJohannes Berg * by the calls to these functions throughout the rest of the code, and must be 290617c18bf8SJohannes Berg * maintained if any of the TX path checks change. 290717c18bf8SJohannes Berg */ 290817c18bf8SJohannes Berg 290917c18bf8SJohannes Berg void ieee80211_check_fast_xmit(struct sta_info *sta) 291017c18bf8SJohannes Berg { 291117c18bf8SJohannes Berg struct ieee80211_fast_tx build = {}, *fast_tx = NULL, *old; 291217c18bf8SJohannes Berg struct ieee80211_local *local = sta->local; 291317c18bf8SJohannes Berg struct ieee80211_sub_if_data *sdata = sta->sdata; 291417c18bf8SJohannes Berg struct ieee80211_hdr *hdr = (void *)build.hdr; 291517c18bf8SJohannes Berg struct ieee80211_chanctx_conf *chanctx_conf; 291617c18bf8SJohannes Berg __le16 fc; 291717c18bf8SJohannes Berg 291830686bf7SJohannes Berg if (!ieee80211_hw_check(&local->hw, SUPPORT_FAST_XMIT)) 291917c18bf8SJohannes Berg return; 292017c18bf8SJohannes Berg 292117c18bf8SJohannes Berg /* Locking here protects both the pointer itself, and against concurrent 292217c18bf8SJohannes Berg * invocations winning data access races to, e.g., the key pointer that 292317c18bf8SJohannes Berg * is used. 292417c18bf8SJohannes Berg * Without it, the invocation of this function right after the key 292517c18bf8SJohannes Berg * pointer changes wouldn't be sufficient, as another CPU could access 292617c18bf8SJohannes Berg * the pointer, then stall, and then do the cache update after the CPU 292717c18bf8SJohannes Berg * that invalidated the key. 292817c18bf8SJohannes Berg * With the locking, such scenarios cannot happen as the check for the 292917c18bf8SJohannes Berg * key and the fast-tx assignment are done atomically, so the CPU that 293017c18bf8SJohannes Berg * modifies the key will either wait or other one will see the key 293117c18bf8SJohannes Berg * cleared/changed already. 293217c18bf8SJohannes Berg */ 293317c18bf8SJohannes Berg spin_lock_bh(&sta->lock); 293430686bf7SJohannes Berg if (ieee80211_hw_check(&local->hw, SUPPORTS_PS) && 293530686bf7SJohannes Berg !ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS) && 293617c18bf8SJohannes Berg sdata->vif.type == NL80211_IFTYPE_STATION) 293717c18bf8SJohannes Berg goto out; 293817c18bf8SJohannes Berg 293917c18bf8SJohannes Berg if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED)) 294017c18bf8SJohannes Berg goto out; 294117c18bf8SJohannes Berg 294217c18bf8SJohannes Berg if (test_sta_flag(sta, WLAN_STA_PS_STA) || 294317c18bf8SJohannes Berg test_sta_flag(sta, WLAN_STA_PS_DRIVER) || 2944f7418bc1SFelix Fietkau test_sta_flag(sta, WLAN_STA_PS_DELIVER) || 2945f7418bc1SFelix Fietkau test_sta_flag(sta, WLAN_STA_CLEAR_PS_FILT)) 294617c18bf8SJohannes Berg goto out; 294717c18bf8SJohannes Berg 294817c18bf8SJohannes Berg if (sdata->noack_map) 294917c18bf8SJohannes Berg goto out; 295017c18bf8SJohannes Berg 295117c18bf8SJohannes Berg /* fast-xmit doesn't handle fragmentation at all */ 2952725b812cSJohannes Berg if (local->hw.wiphy->frag_threshold != (u32)-1 && 2953f3fe4e93SSara Sharon !ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG)) 295417c18bf8SJohannes Berg goto out; 295517c18bf8SJohannes Berg 295617c18bf8SJohannes Berg rcu_read_lock(); 295717c18bf8SJohannes Berg chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 295817c18bf8SJohannes Berg if (!chanctx_conf) { 295917c18bf8SJohannes Berg rcu_read_unlock(); 296017c18bf8SJohannes Berg goto out; 296117c18bf8SJohannes Berg } 296217c18bf8SJohannes Berg build.band = chanctx_conf->def.chan->band; 296317c18bf8SJohannes Berg rcu_read_unlock(); 296417c18bf8SJohannes Berg 296517c18bf8SJohannes Berg fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); 296617c18bf8SJohannes Berg 296717c18bf8SJohannes Berg switch (sdata->vif.type) { 29683ffd8840SJohannes Berg case NL80211_IFTYPE_ADHOC: 29693ffd8840SJohannes Berg /* DA SA BSSID */ 29703ffd8840SJohannes Berg build.da_offs = offsetof(struct ieee80211_hdr, addr1); 29713ffd8840SJohannes Berg build.sa_offs = offsetof(struct ieee80211_hdr, addr2); 29723ffd8840SJohannes Berg memcpy(hdr->addr3, sdata->u.ibss.bssid, ETH_ALEN); 29733ffd8840SJohannes Berg build.hdr_len = 24; 29743ffd8840SJohannes Berg break; 297517c18bf8SJohannes Berg case NL80211_IFTYPE_STATION: 297617c18bf8SJohannes Berg if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { 297717c18bf8SJohannes Berg /* DA SA BSSID */ 297817c18bf8SJohannes Berg build.da_offs = offsetof(struct ieee80211_hdr, addr1); 297917c18bf8SJohannes Berg build.sa_offs = offsetof(struct ieee80211_hdr, addr2); 298017c18bf8SJohannes Berg memcpy(hdr->addr3, sdata->u.mgd.bssid, ETH_ALEN); 298117c18bf8SJohannes Berg build.hdr_len = 24; 298217c18bf8SJohannes Berg break; 298317c18bf8SJohannes Berg } 298417c18bf8SJohannes Berg 298517c18bf8SJohannes Berg if (sdata->u.mgd.use_4addr) { 298617c18bf8SJohannes Berg /* non-regular ethertype cannot use the fastpath */ 298717c18bf8SJohannes Berg fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | 298817c18bf8SJohannes Berg IEEE80211_FCTL_TODS); 298917c18bf8SJohannes Berg /* RA TA DA SA */ 299017c18bf8SJohannes Berg memcpy(hdr->addr1, sdata->u.mgd.bssid, ETH_ALEN); 299117c18bf8SJohannes Berg memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); 299217c18bf8SJohannes Berg build.da_offs = offsetof(struct ieee80211_hdr, addr3); 299317c18bf8SJohannes Berg build.sa_offs = offsetof(struct ieee80211_hdr, addr4); 299417c18bf8SJohannes Berg build.hdr_len = 30; 299517c18bf8SJohannes Berg break; 299617c18bf8SJohannes Berg } 299717c18bf8SJohannes Berg fc |= cpu_to_le16(IEEE80211_FCTL_TODS); 299817c18bf8SJohannes Berg /* BSSID SA DA */ 299917c18bf8SJohannes Berg memcpy(hdr->addr1, sdata->u.mgd.bssid, ETH_ALEN); 300017c18bf8SJohannes Berg build.da_offs = offsetof(struct ieee80211_hdr, addr3); 300117c18bf8SJohannes Berg build.sa_offs = offsetof(struct ieee80211_hdr, addr2); 300217c18bf8SJohannes Berg build.hdr_len = 24; 300317c18bf8SJohannes Berg break; 300417c18bf8SJohannes Berg case NL80211_IFTYPE_AP_VLAN: 300517c18bf8SJohannes Berg if (sdata->wdev.use_4addr) { 300617c18bf8SJohannes Berg fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | 300717c18bf8SJohannes Berg IEEE80211_FCTL_TODS); 300817c18bf8SJohannes Berg /* RA TA DA SA */ 300917c18bf8SJohannes Berg memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN); 301017c18bf8SJohannes Berg memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); 301117c18bf8SJohannes Berg build.da_offs = offsetof(struct ieee80211_hdr, addr3); 301217c18bf8SJohannes Berg build.sa_offs = offsetof(struct ieee80211_hdr, addr4); 301317c18bf8SJohannes Berg build.hdr_len = 30; 301417c18bf8SJohannes Berg break; 301517c18bf8SJohannes Berg } 3016fc0561dcSGustavo A. R. Silva fallthrough; 301717c18bf8SJohannes Berg case NL80211_IFTYPE_AP: 301817c18bf8SJohannes Berg fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); 301917c18bf8SJohannes Berg /* DA BSSID SA */ 302017c18bf8SJohannes Berg build.da_offs = offsetof(struct ieee80211_hdr, addr1); 302117c18bf8SJohannes Berg memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); 302217c18bf8SJohannes Berg build.sa_offs = offsetof(struct ieee80211_hdr, addr3); 302317c18bf8SJohannes Berg build.hdr_len = 24; 302417c18bf8SJohannes Berg break; 302517c18bf8SJohannes Berg default: 302617c18bf8SJohannes Berg /* not handled on fast-xmit */ 302717c18bf8SJohannes Berg goto out; 302817c18bf8SJohannes Berg } 302917c18bf8SJohannes Berg 303017c18bf8SJohannes Berg if (sta->sta.wme) { 303117c18bf8SJohannes Berg build.hdr_len += 2; 303217c18bf8SJohannes Berg fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA); 303317c18bf8SJohannes Berg } 303417c18bf8SJohannes Berg 303517c18bf8SJohannes Berg /* We store the key here so there's no point in using rcu_dereference() 303617c18bf8SJohannes Berg * but that's fine because the code that changes the pointers will call 303717c18bf8SJohannes Berg * this function after doing so. For a single CPU that would be enough, 303817c18bf8SJohannes Berg * for multiple see the comment above. 303917c18bf8SJohannes Berg */ 304017c18bf8SJohannes Berg build.key = rcu_access_pointer(sta->ptk[sta->ptk_idx]); 304117c18bf8SJohannes Berg if (!build.key) 304217c18bf8SJohannes Berg build.key = rcu_access_pointer(sdata->default_unicast_key); 304317c18bf8SJohannes Berg if (build.key) { 3044e495c247SJohannes Berg bool gen_iv, iv_spc, mmic; 304517c18bf8SJohannes Berg 304617c18bf8SJohannes Berg gen_iv = build.key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV; 304717c18bf8SJohannes Berg iv_spc = build.key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE; 30489de18d81SDavid Spinadel mmic = build.key->conf.flags & 30499de18d81SDavid Spinadel (IEEE80211_KEY_FLAG_GENERATE_MMIC | 30509de18d81SDavid Spinadel IEEE80211_KEY_FLAG_PUT_MIC_SPACE); 305117c18bf8SJohannes Berg 305217c18bf8SJohannes Berg /* don't handle software crypto */ 305317c18bf8SJohannes Berg if (!(build.key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) 305417c18bf8SJohannes Berg goto out; 305517c18bf8SJohannes Berg 305662872a9bSAlexander Wetzel /* Key is being removed */ 305762872a9bSAlexander Wetzel if (build.key->flags & KEY_FLAG_TAINTED) 305862872a9bSAlexander Wetzel goto out; 305962872a9bSAlexander Wetzel 306017c18bf8SJohannes Berg switch (build.key->conf.cipher) { 306117c18bf8SJohannes Berg case WLAN_CIPHER_SUITE_CCMP: 306217c18bf8SJohannes Berg case WLAN_CIPHER_SUITE_CCMP_256: 306396fc6efbSAlexander Wetzel if (gen_iv) 306417c18bf8SJohannes Berg build.pn_offs = build.hdr_len; 306517c18bf8SJohannes Berg if (gen_iv || iv_spc) 306617c18bf8SJohannes Berg build.hdr_len += IEEE80211_CCMP_HDR_LEN; 306717c18bf8SJohannes Berg break; 306817c18bf8SJohannes Berg case WLAN_CIPHER_SUITE_GCMP: 306917c18bf8SJohannes Berg case WLAN_CIPHER_SUITE_GCMP_256: 307096fc6efbSAlexander Wetzel if (gen_iv) 307117c18bf8SJohannes Berg build.pn_offs = build.hdr_len; 307217c18bf8SJohannes Berg if (gen_iv || iv_spc) 307317c18bf8SJohannes Berg build.hdr_len += IEEE80211_GCMP_HDR_LEN; 307417c18bf8SJohannes Berg break; 3075e495c247SJohannes Berg case WLAN_CIPHER_SUITE_TKIP: 3076e495c247SJohannes Berg /* cannot handle MMIC or IV generation in xmit-fast */ 3077e495c247SJohannes Berg if (mmic || gen_iv) 307817c18bf8SJohannes Berg goto out; 3079e495c247SJohannes Berg if (iv_spc) 3080e495c247SJohannes Berg build.hdr_len += IEEE80211_TKIP_IV_LEN; 3081e495c247SJohannes Berg break; 3082e495c247SJohannes Berg case WLAN_CIPHER_SUITE_WEP40: 3083e495c247SJohannes Berg case WLAN_CIPHER_SUITE_WEP104: 3084e495c247SJohannes Berg /* cannot handle IV generation in fast-xmit */ 3085e495c247SJohannes Berg if (gen_iv) 3086e495c247SJohannes Berg goto out; 3087e495c247SJohannes Berg if (iv_spc) 3088e495c247SJohannes Berg build.hdr_len += IEEE80211_WEP_IV_LEN; 3089e495c247SJohannes Berg break; 3090e495c247SJohannes Berg case WLAN_CIPHER_SUITE_AES_CMAC: 3091e495c247SJohannes Berg case WLAN_CIPHER_SUITE_BIP_CMAC_256: 3092e495c247SJohannes Berg case WLAN_CIPHER_SUITE_BIP_GMAC_128: 3093e495c247SJohannes Berg case WLAN_CIPHER_SUITE_BIP_GMAC_256: 3094e495c247SJohannes Berg WARN(1, 3095e495c247SJohannes Berg "management cipher suite 0x%x enabled for data\n", 3096e495c247SJohannes Berg build.key->conf.cipher); 3097e495c247SJohannes Berg goto out; 3098e495c247SJohannes Berg default: 3099e495c247SJohannes Berg /* we don't know how to generate IVs for this at all */ 3100e495c247SJohannes Berg if (WARN_ON(gen_iv)) 3101e495c247SJohannes Berg goto out; 3102e495c247SJohannes Berg /* pure hardware keys are OK, of course */ 3103e495c247SJohannes Berg if (!(build.key->flags & KEY_FLAG_CIPHER_SCHEME)) 3104e495c247SJohannes Berg break; 3105e495c247SJohannes Berg /* cipher scheme might require space allocation */ 3106e495c247SJohannes Berg if (iv_spc && 3107e495c247SJohannes Berg build.key->conf.iv_len > IEEE80211_FAST_XMIT_MAX_IV) 3108e495c247SJohannes Berg goto out; 3109e495c247SJohannes Berg if (iv_spc) 3110e495c247SJohannes Berg build.hdr_len += build.key->conf.iv_len; 311117c18bf8SJohannes Berg } 311217c18bf8SJohannes Berg 311317c18bf8SJohannes Berg fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); 311417c18bf8SJohannes Berg } 311517c18bf8SJohannes Berg 311617c18bf8SJohannes Berg hdr->frame_control = fc; 311717c18bf8SJohannes Berg 311817c18bf8SJohannes Berg memcpy(build.hdr + build.hdr_len, 311917c18bf8SJohannes Berg rfc1042_header, sizeof(rfc1042_header)); 312017c18bf8SJohannes Berg build.hdr_len += sizeof(rfc1042_header); 312117c18bf8SJohannes Berg 312217c18bf8SJohannes Berg fast_tx = kmemdup(&build, sizeof(build), GFP_ATOMIC); 312317c18bf8SJohannes Berg /* if the kmemdup fails, continue w/o fast_tx */ 312417c18bf8SJohannes Berg if (!fast_tx) 312517c18bf8SJohannes Berg goto out; 312617c18bf8SJohannes Berg 312717c18bf8SJohannes Berg out: 312817c18bf8SJohannes Berg /* we might have raced against another call to this function */ 312917c18bf8SJohannes Berg old = rcu_dereference_protected(sta->fast_tx, 313017c18bf8SJohannes Berg lockdep_is_held(&sta->lock)); 313117c18bf8SJohannes Berg rcu_assign_pointer(sta->fast_tx, fast_tx); 313217c18bf8SJohannes Berg if (old) 313317c18bf8SJohannes Berg kfree_rcu(old, rcu_head); 313417c18bf8SJohannes Berg spin_unlock_bh(&sta->lock); 313517c18bf8SJohannes Berg } 313617c18bf8SJohannes Berg 313717c18bf8SJohannes Berg void ieee80211_check_fast_xmit_all(struct ieee80211_local *local) 313817c18bf8SJohannes Berg { 313917c18bf8SJohannes Berg struct sta_info *sta; 314017c18bf8SJohannes Berg 314117c18bf8SJohannes Berg rcu_read_lock(); 314217c18bf8SJohannes Berg list_for_each_entry_rcu(sta, &local->sta_list, list) 314317c18bf8SJohannes Berg ieee80211_check_fast_xmit(sta); 314417c18bf8SJohannes Berg rcu_read_unlock(); 314517c18bf8SJohannes Berg } 314617c18bf8SJohannes Berg 314717c18bf8SJohannes Berg void ieee80211_check_fast_xmit_iface(struct ieee80211_sub_if_data *sdata) 314817c18bf8SJohannes Berg { 314917c18bf8SJohannes Berg struct ieee80211_local *local = sdata->local; 315017c18bf8SJohannes Berg struct sta_info *sta; 315117c18bf8SJohannes Berg 315217c18bf8SJohannes Berg rcu_read_lock(); 315317c18bf8SJohannes Berg 315417c18bf8SJohannes Berg list_for_each_entry_rcu(sta, &local->sta_list, list) { 315517c18bf8SJohannes Berg if (sdata != sta->sdata && 315617c18bf8SJohannes Berg (!sta->sdata->bss || sta->sdata->bss != sdata->bss)) 315717c18bf8SJohannes Berg continue; 315817c18bf8SJohannes Berg ieee80211_check_fast_xmit(sta); 315917c18bf8SJohannes Berg } 316017c18bf8SJohannes Berg 316117c18bf8SJohannes Berg rcu_read_unlock(); 316217c18bf8SJohannes Berg } 316317c18bf8SJohannes Berg 316417c18bf8SJohannes Berg void ieee80211_clear_fast_xmit(struct sta_info *sta) 316517c18bf8SJohannes Berg { 316617c18bf8SJohannes Berg struct ieee80211_fast_tx *fast_tx; 316717c18bf8SJohannes Berg 316817c18bf8SJohannes Berg spin_lock_bh(&sta->lock); 316917c18bf8SJohannes Berg fast_tx = rcu_dereference_protected(sta->fast_tx, 317017c18bf8SJohannes Berg lockdep_is_held(&sta->lock)); 317117c18bf8SJohannes Berg RCU_INIT_POINTER(sta->fast_tx, NULL); 317217c18bf8SJohannes Berg spin_unlock_bh(&sta->lock); 317317c18bf8SJohannes Berg 317417c18bf8SJohannes Berg if (fast_tx) 317517c18bf8SJohannes Berg kfree_rcu(fast_tx, rcu_head); 317617c18bf8SJohannes Berg } 317717c18bf8SJohannes Berg 31786e0456b5SFelix Fietkau static bool ieee80211_amsdu_realloc_pad(struct ieee80211_local *local, 3179166ac9d5SSara Sharon struct sk_buff *skb, int headroom) 31806e0456b5SFelix Fietkau { 3181166ac9d5SSara Sharon if (skb_headroom(skb) < headroom) { 31826e0456b5SFelix Fietkau I802_DEBUG_INC(local->tx_expand_skb_head); 31836e0456b5SFelix Fietkau 3184166ac9d5SSara Sharon if (pskb_expand_head(skb, headroom, 0, GFP_ATOMIC)) { 31856e0456b5SFelix Fietkau wiphy_debug(local->hw.wiphy, 31866e0456b5SFelix Fietkau "failed to reallocate TX buffer\n"); 31876e0456b5SFelix Fietkau return false; 31886e0456b5SFelix Fietkau } 31896e0456b5SFelix Fietkau } 31906e0456b5SFelix Fietkau 31916e0456b5SFelix Fietkau return true; 31926e0456b5SFelix Fietkau } 31936e0456b5SFelix Fietkau 31946e0456b5SFelix Fietkau static bool ieee80211_amsdu_prepare_head(struct ieee80211_sub_if_data *sdata, 31956e0456b5SFelix Fietkau struct ieee80211_fast_tx *fast_tx, 31966e0456b5SFelix Fietkau struct sk_buff *skb) 31976e0456b5SFelix Fietkau { 31986e0456b5SFelix Fietkau struct ieee80211_local *local = sdata->local; 31996e0456b5SFelix Fietkau struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 32006e0456b5SFelix Fietkau struct ieee80211_hdr *hdr; 320106f2bb1eSMichael Braun struct ethhdr *amsdu_hdr; 32026e0456b5SFelix Fietkau int hdr_len = fast_tx->hdr_len - sizeof(rfc1042_header); 32036e0456b5SFelix Fietkau int subframe_len = skb->len - hdr_len; 32046e0456b5SFelix Fietkau void *data; 320506f2bb1eSMichael Braun u8 *qc, *h_80211_src, *h_80211_dst; 3206a3e2f4b6SMichael Braun const u8 *bssid; 32076e0456b5SFelix Fietkau 32086e0456b5SFelix Fietkau if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) 32096e0456b5SFelix Fietkau return false; 32106e0456b5SFelix Fietkau 32116e0456b5SFelix Fietkau if (info->control.flags & IEEE80211_TX_CTRL_AMSDU) 32126e0456b5SFelix Fietkau return true; 32136e0456b5SFelix Fietkau 3214166ac9d5SSara Sharon if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(*amsdu_hdr))) 32156e0456b5SFelix Fietkau return false; 32166e0456b5SFelix Fietkau 321706f2bb1eSMichael Braun data = skb_push(skb, sizeof(*amsdu_hdr)); 321806f2bb1eSMichael Braun memmove(data, data + sizeof(*amsdu_hdr), hdr_len); 32196e0456b5SFelix Fietkau hdr = data; 322006f2bb1eSMichael Braun amsdu_hdr = data + hdr_len; 322106f2bb1eSMichael Braun /* h_80211_src/dst is addr* field within hdr */ 322206f2bb1eSMichael Braun h_80211_src = data + fast_tx->sa_offs; 322306f2bb1eSMichael Braun h_80211_dst = data + fast_tx->da_offs; 322406f2bb1eSMichael Braun 322506f2bb1eSMichael Braun amsdu_hdr->h_proto = cpu_to_be16(subframe_len); 322606f2bb1eSMichael Braun ether_addr_copy(amsdu_hdr->h_source, h_80211_src); 322706f2bb1eSMichael Braun ether_addr_copy(amsdu_hdr->h_dest, h_80211_dst); 322806f2bb1eSMichael Braun 3229a3e2f4b6SMichael Braun /* according to IEEE 802.11-2012 8.3.2 table 8-19, the outer SA/DA 3230a3e2f4b6SMichael Braun * fields needs to be changed to BSSID for A-MSDU frames depending 3231a3e2f4b6SMichael Braun * on FromDS/ToDS values. 3232a3e2f4b6SMichael Braun */ 3233a3e2f4b6SMichael Braun switch (sdata->vif.type) { 3234a3e2f4b6SMichael Braun case NL80211_IFTYPE_STATION: 3235a3e2f4b6SMichael Braun bssid = sdata->u.mgd.bssid; 3236a3e2f4b6SMichael Braun break; 3237a3e2f4b6SMichael Braun case NL80211_IFTYPE_AP: 3238a3e2f4b6SMichael Braun case NL80211_IFTYPE_AP_VLAN: 3239a3e2f4b6SMichael Braun bssid = sdata->vif.addr; 3240a3e2f4b6SMichael Braun break; 3241a3e2f4b6SMichael Braun default: 3242a3e2f4b6SMichael Braun bssid = NULL; 3243a3e2f4b6SMichael Braun } 3244a3e2f4b6SMichael Braun 3245a3e2f4b6SMichael Braun if (bssid && ieee80211_has_fromds(hdr->frame_control)) 3246a3e2f4b6SMichael Braun ether_addr_copy(h_80211_src, bssid); 3247a3e2f4b6SMichael Braun 3248a3e2f4b6SMichael Braun if (bssid && ieee80211_has_tods(hdr->frame_control)) 3249a3e2f4b6SMichael Braun ether_addr_copy(h_80211_dst, bssid); 3250a3e2f4b6SMichael Braun 32516e0456b5SFelix Fietkau qc = ieee80211_get_qos_ctl(hdr); 32526e0456b5SFelix Fietkau *qc |= IEEE80211_QOS_CTL_A_MSDU_PRESENT; 32536e0456b5SFelix Fietkau 32546e0456b5SFelix Fietkau info->control.flags |= IEEE80211_TX_CTRL_AMSDU; 32556e0456b5SFelix Fietkau 32566e0456b5SFelix Fietkau return true; 32576e0456b5SFelix Fietkau } 32586e0456b5SFelix Fietkau 32596e0456b5SFelix Fietkau static bool ieee80211_amsdu_aggregate(struct ieee80211_sub_if_data *sdata, 32606e0456b5SFelix Fietkau struct sta_info *sta, 32616e0456b5SFelix Fietkau struct ieee80211_fast_tx *fast_tx, 32626e0456b5SFelix Fietkau struct sk_buff *skb) 32636e0456b5SFelix Fietkau { 32646e0456b5SFelix Fietkau struct ieee80211_local *local = sdata->local; 3265fa962b92SMichal Kazior struct fq *fq = &local->fq; 3266fa962b92SMichal Kazior struct fq_tin *tin; 3267fa962b92SMichal Kazior struct fq_flow *flow; 32686e0456b5SFelix Fietkau u8 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; 32696e0456b5SFelix Fietkau struct ieee80211_txq *txq = sta->sta.txq[tid]; 32706e0456b5SFelix Fietkau struct txq_info *txqi; 32716e0456b5SFelix Fietkau struct sk_buff **frag_tail, *head; 32726e0456b5SFelix Fietkau int subframe_len = skb->len - ETH_ALEN; 32736e0456b5SFelix Fietkau u8 max_subframes = sta->sta.max_amsdu_subframes; 32746e0456b5SFelix Fietkau int max_frags = local->hw.max_tx_fragments; 32756e0456b5SFelix Fietkau int max_amsdu_len = sta->sta.max_amsdu_len; 3276eb9b64e3SFelix Fietkau int orig_truesize; 3277f2af2df8SFelix Fietkau u32 flow_idx; 32786e0456b5SFelix Fietkau __be16 len; 32796e0456b5SFelix Fietkau void *data; 32806e0456b5SFelix Fietkau bool ret = false; 3281fa962b92SMichal Kazior unsigned int orig_len; 328266eb02d8SLorenzo Bianconi int n = 2, nfrags, pad = 0; 3283166ac9d5SSara Sharon u16 hdrlen; 32846e0456b5SFelix Fietkau 32856e0456b5SFelix Fietkau if (!ieee80211_hw_check(&local->hw, TX_AMSDU)) 32866e0456b5SFelix Fietkau return false; 32876e0456b5SFelix Fietkau 3288344f8e00SSara Sharon if (skb_is_gso(skb)) 3289344f8e00SSara Sharon return false; 3290344f8e00SSara Sharon 32916e0456b5SFelix Fietkau if (!txq) 32926e0456b5SFelix Fietkau return false; 32936e0456b5SFelix Fietkau 32946e0456b5SFelix Fietkau txqi = to_txq_info(txq); 32956e0456b5SFelix Fietkau if (test_bit(IEEE80211_TXQ_NO_AMSDU, &txqi->flags)) 32966e0456b5SFelix Fietkau return false; 32976e0456b5SFelix Fietkau 32986e0456b5SFelix Fietkau if (sta->sta.max_rc_amsdu_len) 32996e0456b5SFelix Fietkau max_amsdu_len = min_t(int, max_amsdu_len, 33006e0456b5SFelix Fietkau sta->sta.max_rc_amsdu_len); 33016e0456b5SFelix Fietkau 3302edba6bdaSSara Sharon if (sta->sta.max_tid_amsdu_len[tid]) 3303edba6bdaSSara Sharon max_amsdu_len = min_t(int, max_amsdu_len, 3304edba6bdaSSara Sharon sta->sta.max_tid_amsdu_len[tid]); 3305edba6bdaSSara Sharon 3306f2af2df8SFelix Fietkau flow_idx = fq_flow_idx(fq, skb); 3307f2af2df8SFelix Fietkau 3308fa962b92SMichal Kazior spin_lock_bh(&fq->lock); 33096e0456b5SFelix Fietkau 3310fa962b92SMichal Kazior /* TODO: Ideally aggregation should be done on dequeue to remain 3311fa962b92SMichal Kazior * responsive to environment changes. 3312fa962b92SMichal Kazior */ 3313fa962b92SMichal Kazior 3314fa962b92SMichal Kazior tin = &txqi->tin; 3315bf9009bfSFelix Fietkau flow = fq_flow_classify(fq, tin, flow_idx, skb); 3316fa962b92SMichal Kazior head = skb_peek_tail(&flow->queue); 3317344f8e00SSara Sharon if (!head || skb_is_gso(head)) 33186e0456b5SFelix Fietkau goto out; 33196e0456b5SFelix Fietkau 3320eb9b64e3SFelix Fietkau orig_truesize = head->truesize; 3321fa962b92SMichal Kazior orig_len = head->len; 3322fa962b92SMichal Kazior 33236e0456b5SFelix Fietkau if (skb->len + head->len > max_amsdu_len) 33246e0456b5SFelix Fietkau goto out; 33256e0456b5SFelix Fietkau 33266e0456b5SFelix Fietkau nfrags = 1 + skb_shinfo(skb)->nr_frags; 33276e0456b5SFelix Fietkau nfrags += 1 + skb_shinfo(head)->nr_frags; 33286e0456b5SFelix Fietkau frag_tail = &skb_shinfo(head)->frag_list; 33296e0456b5SFelix Fietkau while (*frag_tail) { 33306e0456b5SFelix Fietkau nfrags += 1 + skb_shinfo(*frag_tail)->nr_frags; 33316e0456b5SFelix Fietkau frag_tail = &(*frag_tail)->next; 33326e0456b5SFelix Fietkau n++; 33336e0456b5SFelix Fietkau } 33346e0456b5SFelix Fietkau 33356e0456b5SFelix Fietkau if (max_subframes && n > max_subframes) 33366e0456b5SFelix Fietkau goto out; 33376e0456b5SFelix Fietkau 33386e0456b5SFelix Fietkau if (max_frags && nfrags > max_frags) 33396e0456b5SFelix Fietkau goto out; 33406e0456b5SFelix Fietkau 33419739fe29SSara Sharon if (!drv_can_aggregate_in_amsdu(local, head, skb)) 33429739fe29SSara Sharon goto out; 33439739fe29SSara Sharon 33441eb50790SLorenzo Bianconi if (!ieee80211_amsdu_prepare_head(sdata, fast_tx, head)) 33456e0456b5SFelix Fietkau goto out; 33466e0456b5SFelix Fietkau 3347166ac9d5SSara Sharon /* 3348166ac9d5SSara Sharon * Pad out the previous subframe to a multiple of 4 by adding the 3349166ac9d5SSara Sharon * padding to the next one, that's being added. Note that head->len 3350166ac9d5SSara Sharon * is the length of the full A-MSDU, but that works since each time 3351166ac9d5SSara Sharon * we add a new subframe we pad out the previous one to a multiple 3352166ac9d5SSara Sharon * of 4 and thus it no longer matters in the next round. 3353166ac9d5SSara Sharon */ 3354166ac9d5SSara Sharon hdrlen = fast_tx->hdr_len - sizeof(rfc1042_header); 3355166ac9d5SSara Sharon if ((head->len - hdrlen) & 3) 3356166ac9d5SSara Sharon pad = 4 - ((head->len - hdrlen) & 3); 3357166ac9d5SSara Sharon 3358166ac9d5SSara Sharon if (!ieee80211_amsdu_realloc_pad(local, skb, sizeof(rfc1042_header) + 3359166ac9d5SSara Sharon 2 + pad)) 3360aa58acf3SJohannes Berg goto out_recalc; 33616e0456b5SFelix Fietkau 33626e0456b5SFelix Fietkau ret = true; 33636e0456b5SFelix Fietkau data = skb_push(skb, ETH_ALEN + 2); 33646e0456b5SFelix Fietkau memmove(data, data + ETH_ALEN + 2, 2 * ETH_ALEN); 33656e0456b5SFelix Fietkau 33666e0456b5SFelix Fietkau data += 2 * ETH_ALEN; 33676e0456b5SFelix Fietkau len = cpu_to_be16(subframe_len); 33686e0456b5SFelix Fietkau memcpy(data, &len, 2); 33696e0456b5SFelix Fietkau memcpy(data + 2, rfc1042_header, sizeof(rfc1042_header)); 33706e0456b5SFelix Fietkau 3371166ac9d5SSara Sharon memset(skb_push(skb, pad), 0, pad); 3372166ac9d5SSara Sharon 33736e0456b5SFelix Fietkau head->len += skb->len; 33746e0456b5SFelix Fietkau head->data_len += skb->len; 33756e0456b5SFelix Fietkau *frag_tail = skb; 33766e0456b5SFelix Fietkau 3377aa58acf3SJohannes Berg out_recalc: 3378eb9b64e3SFelix Fietkau fq->memory_usage += head->truesize - orig_truesize; 3379aa58acf3SJohannes Berg if (head->len != orig_len) { 3380fa962b92SMichal Kazior flow->backlog += head->len - orig_len; 3381fa962b92SMichal Kazior tin->backlog_bytes += head->len - orig_len; 3382aa58acf3SJohannes Berg } 33836e0456b5SFelix Fietkau out: 3384fa962b92SMichal Kazior spin_unlock_bh(&fq->lock); 33856e0456b5SFelix Fietkau 33866e0456b5SFelix Fietkau return ret; 33876e0456b5SFelix Fietkau } 33886e0456b5SFelix Fietkau 3389bb42f2d1SToke Høiland-Jørgensen /* 3390bb42f2d1SToke Høiland-Jørgensen * Can be called while the sta lock is held. Anything that can cause packets to 3391bb42f2d1SToke Høiland-Jørgensen * be generated will cause deadlock! 3392bb42f2d1SToke Høiland-Jørgensen */ 3393*03c3911dSRyder Lee static ieee80211_tx_result 3394*03c3911dSRyder Lee ieee80211_xmit_fast_finish(struct ieee80211_sub_if_data *sdata, 3395bb42f2d1SToke Høiland-Jørgensen struct sta_info *sta, u8 pn_offs, 3396bb42f2d1SToke Høiland-Jørgensen struct ieee80211_key *key, 3397*03c3911dSRyder Lee struct ieee80211_tx_data *tx) 3398bb42f2d1SToke Høiland-Jørgensen { 3399*03c3911dSRyder Lee struct sk_buff *skb = tx->skb; 3400bb42f2d1SToke Høiland-Jørgensen struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 3401bb42f2d1SToke Høiland-Jørgensen struct ieee80211_hdr *hdr = (void *)skb->data; 3402bb42f2d1SToke Høiland-Jørgensen u8 tid = IEEE80211_NUM_TIDS; 3403bb42f2d1SToke Høiland-Jørgensen 3404*03c3911dSRyder Lee if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL) && 3405*03c3911dSRyder Lee ieee80211_tx_h_rate_ctrl(tx) != TX_CONTINUE) 3406*03c3911dSRyder Lee return TX_DROP; 3407*03c3911dSRyder Lee 3408bb42f2d1SToke Høiland-Jørgensen if (key) 3409bb42f2d1SToke Høiland-Jørgensen info->control.hw_key = &key->conf; 3410bb42f2d1SToke Høiland-Jørgensen 341136ec144fSLev Stipakov dev_sw_netstats_tx_add(skb->dev, 1, skb->len); 3412bb42f2d1SToke Høiland-Jørgensen 3413bb42f2d1SToke Høiland-Jørgensen if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) { 3414bb42f2d1SToke Høiland-Jørgensen tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; 3415bb42f2d1SToke Høiland-Jørgensen hdr->seq_ctrl = ieee80211_tx_next_seq(sta, tid); 3416bb42f2d1SToke Høiland-Jørgensen } else { 3417bb42f2d1SToke Høiland-Jørgensen info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; 3418bb42f2d1SToke Høiland-Jørgensen hdr->seq_ctrl = cpu_to_le16(sdata->sequence_number); 3419bb42f2d1SToke Høiland-Jørgensen sdata->sequence_number += 0x10; 3420bb42f2d1SToke Høiland-Jørgensen } 3421bb42f2d1SToke Høiland-Jørgensen 3422bb42f2d1SToke Høiland-Jørgensen if (skb_shinfo(skb)->gso_size) 3423bb42f2d1SToke Høiland-Jørgensen sta->tx_stats.msdu[tid] += 3424bb42f2d1SToke Høiland-Jørgensen DIV_ROUND_UP(skb->len, skb_shinfo(skb)->gso_size); 3425bb42f2d1SToke Høiland-Jørgensen else 3426bb42f2d1SToke Høiland-Jørgensen sta->tx_stats.msdu[tid]++; 3427bb42f2d1SToke Høiland-Jørgensen 3428bb42f2d1SToke Høiland-Jørgensen info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)]; 3429bb42f2d1SToke Høiland-Jørgensen 3430bb42f2d1SToke Høiland-Jørgensen /* statistics normally done by ieee80211_tx_h_stats (but that 3431bb42f2d1SToke Høiland-Jørgensen * has to consider fragmentation, so is more complex) 3432bb42f2d1SToke Høiland-Jørgensen */ 3433bb42f2d1SToke Høiland-Jørgensen sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len; 3434bb42f2d1SToke Høiland-Jørgensen sta->tx_stats.packets[skb_get_queue_mapping(skb)]++; 3435bb42f2d1SToke Høiland-Jørgensen 3436bb42f2d1SToke Høiland-Jørgensen if (pn_offs) { 3437bb42f2d1SToke Høiland-Jørgensen u64 pn; 3438bb42f2d1SToke Høiland-Jørgensen u8 *crypto_hdr = skb->data + pn_offs; 3439bb42f2d1SToke Høiland-Jørgensen 3440bb42f2d1SToke Høiland-Jørgensen switch (key->conf.cipher) { 3441bb42f2d1SToke Høiland-Jørgensen case WLAN_CIPHER_SUITE_CCMP: 3442bb42f2d1SToke Høiland-Jørgensen case WLAN_CIPHER_SUITE_CCMP_256: 3443bb42f2d1SToke Høiland-Jørgensen case WLAN_CIPHER_SUITE_GCMP: 3444bb42f2d1SToke Høiland-Jørgensen case WLAN_CIPHER_SUITE_GCMP_256: 3445bb42f2d1SToke Høiland-Jørgensen pn = atomic64_inc_return(&key->conf.tx_pn); 3446bb42f2d1SToke Høiland-Jørgensen crypto_hdr[0] = pn; 3447bb42f2d1SToke Høiland-Jørgensen crypto_hdr[1] = pn >> 8; 344896fc6efbSAlexander Wetzel crypto_hdr[3] = 0x20 | (key->conf.keyidx << 6); 3449bb42f2d1SToke Høiland-Jørgensen crypto_hdr[4] = pn >> 16; 3450bb42f2d1SToke Høiland-Jørgensen crypto_hdr[5] = pn >> 24; 3451bb42f2d1SToke Høiland-Jørgensen crypto_hdr[6] = pn >> 32; 3452bb42f2d1SToke Høiland-Jørgensen crypto_hdr[7] = pn >> 40; 3453bb42f2d1SToke Høiland-Jørgensen break; 3454bb42f2d1SToke Høiland-Jørgensen } 3455bb42f2d1SToke Høiland-Jørgensen } 3456*03c3911dSRyder Lee 3457*03c3911dSRyder Lee return TX_CONTINUE; 3458bb42f2d1SToke Høiland-Jørgensen } 3459bb42f2d1SToke Høiland-Jørgensen 346017c18bf8SJohannes Berg static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, 3461bb42f2d1SToke Høiland-Jørgensen struct sta_info *sta, 346217c18bf8SJohannes Berg struct ieee80211_fast_tx *fast_tx, 346317c18bf8SJohannes Berg struct sk_buff *skb) 346417c18bf8SJohannes Berg { 346517c18bf8SJohannes Berg struct ieee80211_local *local = sdata->local; 346617c18bf8SJohannes Berg u16 ethertype = (skb->data[12] << 8) | skb->data[13]; 346717c18bf8SJohannes Berg int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2); 346817c18bf8SJohannes Berg int hw_headroom = sdata->local->hw.extra_tx_headroom; 346917c18bf8SJohannes Berg struct ethhdr eth; 347035f432a0SJohannes Berg struct ieee80211_tx_info *info; 347117c18bf8SJohannes Berg struct ieee80211_hdr *hdr = (void *)fast_tx->hdr; 347217c18bf8SJohannes Berg struct ieee80211_tx_data tx; 347317c18bf8SJohannes Berg ieee80211_tx_result r; 347417c18bf8SJohannes Berg struct tid_ampdu_tx *tid_tx = NULL; 347517c18bf8SJohannes Berg u8 tid = IEEE80211_NUM_TIDS; 347617c18bf8SJohannes Berg 347717c18bf8SJohannes Berg /* control port protocol needs a lot of special handling */ 347817c18bf8SJohannes Berg if (cpu_to_be16(ethertype) == sdata->control_port_protocol) 347917c18bf8SJohannes Berg return false; 348017c18bf8SJohannes Berg 348117c18bf8SJohannes Berg /* only RFC 1042 SNAP */ 348217c18bf8SJohannes Berg if (ethertype < ETH_P_802_3_MIN) 348317c18bf8SJohannes Berg return false; 348417c18bf8SJohannes Berg 348517c18bf8SJohannes Berg /* don't handle TX status request here either */ 348617c18bf8SJohannes Berg if (skb->sk && skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS) 348717c18bf8SJohannes Berg return false; 348817c18bf8SJohannes Berg 348917c18bf8SJohannes Berg if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) { 349017c18bf8SJohannes Berg tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; 349117c18bf8SJohannes Berg tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]); 3492472be00dSJohannes Berg if (tid_tx) { 3493472be00dSJohannes Berg if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) 349417c18bf8SJohannes Berg return false; 3495472be00dSJohannes Berg if (tid_tx->timeout) 3496472be00dSJohannes Berg tid_tx->last_tx = jiffies; 3497472be00dSJohannes Berg } 349817c18bf8SJohannes Berg } 349917c18bf8SJohannes Berg 350017c18bf8SJohannes Berg /* after this point (skb is modified) we cannot return false */ 350117c18bf8SJohannes Berg 350217c18bf8SJohannes Berg if (skb_shared(skb)) { 350317c18bf8SJohannes Berg struct sk_buff *tmp_skb = skb; 350417c18bf8SJohannes Berg 350517c18bf8SJohannes Berg skb = skb_clone(skb, GFP_ATOMIC); 350617c18bf8SJohannes Berg kfree_skb(tmp_skb); 350717c18bf8SJohannes Berg 350817c18bf8SJohannes Berg if (!skb) 350917c18bf8SJohannes Berg return true; 351017c18bf8SJohannes Berg } 351117c18bf8SJohannes Berg 35126e0456b5SFelix Fietkau if ((hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) && 35136e0456b5SFelix Fietkau ieee80211_amsdu_aggregate(sdata, sta, fast_tx, skb)) 35146e0456b5SFelix Fietkau return true; 35156e0456b5SFelix Fietkau 351617c18bf8SJohannes Berg /* will not be crypto-handled beyond what we do here, so use false 351717c18bf8SJohannes Berg * as the may-encrypt argument for the resize to not account for 351817c18bf8SJohannes Berg * more room than we already have in 'extra_head' 351917c18bf8SJohannes Berg */ 352017c18bf8SJohannes Berg if (unlikely(ieee80211_skb_resize(sdata, skb, 352117c18bf8SJohannes Berg max_t(int, extra_head + hw_headroom - 352217c18bf8SJohannes Berg skb_headroom(skb), 0), 352314f46c1eSJohannes Berg ENCRYPT_NO))) { 352417c18bf8SJohannes Berg kfree_skb(skb); 352517c18bf8SJohannes Berg return true; 352617c18bf8SJohannes Berg } 352717c18bf8SJohannes Berg 352817c18bf8SJohannes Berg memcpy(ð, skb->data, ETH_HLEN - 2); 3529d58ff351SJohannes Berg hdr = skb_push(skb, extra_head); 353017c18bf8SJohannes Berg memcpy(skb->data, fast_tx->hdr, fast_tx->hdr_len); 353117c18bf8SJohannes Berg memcpy(skb->data + fast_tx->da_offs, eth.h_dest, ETH_ALEN); 353217c18bf8SJohannes Berg memcpy(skb->data + fast_tx->sa_offs, eth.h_source, ETH_ALEN); 353317c18bf8SJohannes Berg 353435f432a0SJohannes Berg info = IEEE80211_SKB_CB(skb); 353517c18bf8SJohannes Berg memset(info, 0, sizeof(*info)); 353617c18bf8SJohannes Berg info->band = fast_tx->band; 353717c18bf8SJohannes Berg info->control.vif = &sdata->vif; 353817c18bf8SJohannes Berg info->flags = IEEE80211_TX_CTL_FIRST_FRAGMENT | 353917c18bf8SJohannes Berg IEEE80211_TX_CTL_DONTFRAG | 354017c18bf8SJohannes Berg (tid_tx ? IEEE80211_TX_CTL_AMPDU : 0); 3541bb42f2d1SToke Høiland-Jørgensen info->control.flags = IEEE80211_TX_CTRL_FAST_XMIT; 354217c18bf8SJohannes Berg 3543276d9e82SJulius Niedworok #ifdef CONFIG_MAC80211_DEBUGFS 3544276d9e82SJulius Niedworok if (local->force_tx_status) 3545276d9e82SJulius Niedworok info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; 3546276d9e82SJulius Niedworok #endif 3547276d9e82SJulius Niedworok 3548a786f96dSFelix Fietkau if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) { 3549a786f96dSFelix Fietkau tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; 3550a786f96dSFelix Fietkau *ieee80211_get_qos_ctl(hdr) = tid; 3551a786f96dSFelix Fietkau } 3552a786f96dSFelix Fietkau 355317c18bf8SJohannes Berg __skb_queue_head_init(&tx.skbs); 355417c18bf8SJohannes Berg 355517c18bf8SJohannes Berg tx.flags = IEEE80211_TX_UNICAST; 355617c18bf8SJohannes Berg tx.local = local; 355717c18bf8SJohannes Berg tx.sdata = sdata; 355817c18bf8SJohannes Berg tx.sta = sta; 355917c18bf8SJohannes Berg tx.key = fast_tx->key; 356017c18bf8SJohannes Berg 3561bb42f2d1SToke Høiland-Jørgensen if (ieee80211_queue_skb(local, sdata, sta, skb)) 3562bb42f2d1SToke Høiland-Jørgensen return true; 356317c18bf8SJohannes Berg 3564*03c3911dSRyder Lee tx.skb = skb; 3565*03c3911dSRyder Lee r = ieee80211_xmit_fast_finish(sdata, sta, fast_tx->pn_offs, 3566*03c3911dSRyder Lee fast_tx->key, &tx); 3567*03c3911dSRyder Lee tx.skb = NULL; 3568*03c3911dSRyder Lee if (r == TX_DROP) { 3569*03c3911dSRyder Lee kfree_skb(skb); 3570*03c3911dSRyder Lee return true; 3571*03c3911dSRyder Lee } 357217c18bf8SJohannes Berg 357317c18bf8SJohannes Berg if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 357417c18bf8SJohannes Berg sdata = container_of(sdata->bss, 357517c18bf8SJohannes Berg struct ieee80211_sub_if_data, u.ap); 357617c18bf8SJohannes Berg 357717c18bf8SJohannes Berg __skb_queue_tail(&tx.skbs, skb); 35784fd0328dSJohannes Berg ieee80211_tx_frags(local, &sdata->vif, sta, &tx.skbs, false); 357917c18bf8SJohannes Berg return true; 358017c18bf8SJohannes Berg } 358117c18bf8SJohannes Berg 3582e0e2efffSToke Høiland-Jørgensen struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, 3583e0e2efffSToke Høiland-Jørgensen struct ieee80211_txq *txq) 3584e0e2efffSToke Høiland-Jørgensen { 3585e0e2efffSToke Høiland-Jørgensen struct ieee80211_local *local = hw_to_local(hw); 3586e0e2efffSToke Høiland-Jørgensen struct txq_info *txqi = container_of(txq, struct txq_info, txq); 3587e0e2efffSToke Høiland-Jørgensen struct ieee80211_hdr *hdr; 3588e0e2efffSToke Høiland-Jørgensen struct sk_buff *skb = NULL; 3589e0e2efffSToke Høiland-Jørgensen struct fq *fq = &local->fq; 3590e0e2efffSToke Høiland-Jørgensen struct fq_tin *tin = &txqi->tin; 3591bb42f2d1SToke Høiland-Jørgensen struct ieee80211_tx_info *info; 3592bb42f2d1SToke Høiland-Jørgensen struct ieee80211_tx_data tx; 3593bb42f2d1SToke Høiland-Jørgensen ieee80211_tx_result r; 359421a5d4c3SManikanta Pubbisetty struct ieee80211_vif *vif = txq->vif; 3595e0e2efffSToke Høiland-Jørgensen 3596fb0e76abSErik Stromdahl WARN_ON_ONCE(softirq_count() == 0); 3597fb0e76abSErik Stromdahl 35987a89233aSToke Høiland-Jørgensen if (!ieee80211_txq_airtime_check(hw, txq)) 35997a89233aSToke Høiland-Jørgensen return NULL; 36007a89233aSToke Høiland-Jørgensen 3601ded4698bSFelix Fietkau begin: 3602e0e2efffSToke Høiland-Jørgensen spin_lock_bh(&fq->lock); 3603e0e2efffSToke Høiland-Jørgensen 360421a5d4c3SManikanta Pubbisetty if (test_bit(IEEE80211_TXQ_STOP, &txqi->flags) || 360521a5d4c3SManikanta Pubbisetty test_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags)) 3606e0e2efffSToke Høiland-Jørgensen goto out; 3607e0e2efffSToke Høiland-Jørgensen 36081153a747SJohannes Berg if (vif->txqs_stopped[txq->ac]) { 360921a5d4c3SManikanta Pubbisetty set_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags); 361021a5d4c3SManikanta Pubbisetty goto out; 361121a5d4c3SManikanta Pubbisetty } 361221a5d4c3SManikanta Pubbisetty 3613bb42f2d1SToke Høiland-Jørgensen /* Make sure fragments stay together. */ 3614bb42f2d1SToke Høiland-Jørgensen skb = __skb_dequeue(&txqi->frags); 3615ca47b462SJohannes Berg if (unlikely(skb)) { 3616ca47b462SJohannes Berg if (!(IEEE80211_SKB_CB(skb)->control.flags & 3617ca47b462SJohannes Berg IEEE80211_TX_INTCFL_NEED_TXPROCESSING)) 3618bb42f2d1SToke Høiland-Jørgensen goto out; 3619ca47b462SJohannes Berg IEEE80211_SKB_CB(skb)->control.flags &= 3620ca47b462SJohannes Berg ~IEEE80211_TX_INTCFL_NEED_TXPROCESSING; 3621ca47b462SJohannes Berg } else { 3622e0e2efffSToke Høiland-Jørgensen skb = fq_tin_dequeue(fq, tin, fq_tin_dequeue_func); 3623ca47b462SJohannes Berg } 3624ca47b462SJohannes Berg 3625e0e2efffSToke Høiland-Jørgensen if (!skb) 3626e0e2efffSToke Høiland-Jørgensen goto out; 3627e0e2efffSToke Høiland-Jørgensen 3628ded4698bSFelix Fietkau spin_unlock_bh(&fq->lock); 3629ded4698bSFelix Fietkau 3630e0e2efffSToke Høiland-Jørgensen hdr = (struct ieee80211_hdr *)skb->data; 3631bb42f2d1SToke Høiland-Jørgensen info = IEEE80211_SKB_CB(skb); 3632bb42f2d1SToke Høiland-Jørgensen 3633bb42f2d1SToke Høiland-Jørgensen memset(&tx, 0, sizeof(tx)); 3634bb42f2d1SToke Høiland-Jørgensen __skb_queue_head_init(&tx.skbs); 3635bb42f2d1SToke Høiland-Jørgensen tx.local = local; 3636bb42f2d1SToke Høiland-Jørgensen tx.skb = skb; 3637bb42f2d1SToke Høiland-Jørgensen tx.sdata = vif_to_sdata(info->control.vif); 3638bb42f2d1SToke Høiland-Jørgensen 3639804fc6a2SMathy Vanhoef if (txq->sta) { 3640bb42f2d1SToke Høiland-Jørgensen tx.sta = container_of(txq->sta, struct sta_info, sta); 3641ce2e1ca7SJouni Malinen /* 3642ce2e1ca7SJouni Malinen * Drop unicast frames to unauthorised stations unless they are 3643804fc6a2SMathy Vanhoef * injected frames or EAPOL frames from the local station. 3644ce2e1ca7SJouni Malinen */ 3645804fc6a2SMathy Vanhoef if (unlikely(!(info->flags & IEEE80211_TX_CTL_INJECTED) && 3646804fc6a2SMathy Vanhoef ieee80211_is_data(hdr->frame_control) && 3647be8c827fSJohannes Berg !ieee80211_vif_is_mesh(&tx.sdata->vif) && 3648ce2e1ca7SJouni Malinen tx.sdata->vif.type != NL80211_IFTYPE_OCB && 3649ce2e1ca7SJouni Malinen !is_multicast_ether_addr(hdr->addr1) && 3650ce2e1ca7SJouni Malinen !test_sta_flag(tx.sta, WLAN_STA_AUTHORIZED) && 3651ce2e1ca7SJouni Malinen (!(info->control.flags & 3652ce2e1ca7SJouni Malinen IEEE80211_TX_CTRL_PORT_CTRL_PROTO) || 3653ce2e1ca7SJouni Malinen !ether_addr_equal(tx.sdata->vif.addr, 3654ce2e1ca7SJouni Malinen hdr->addr2)))) { 3655ce2e1ca7SJouni Malinen I802_DEBUG_INC(local->tx_handlers_drop_unauth_port); 3656ce2e1ca7SJouni Malinen ieee80211_free_txskb(&local->hw, skb); 3657ce2e1ca7SJouni Malinen goto begin; 3658ce2e1ca7SJouni Malinen } 3659ce2e1ca7SJouni Malinen } 3660bb42f2d1SToke Høiland-Jørgensen 3661bb42f2d1SToke Høiland-Jørgensen /* 3662bb42f2d1SToke Høiland-Jørgensen * The key can be removed while the packet was queued, so need to call 3663bb42f2d1SToke Høiland-Jørgensen * this here to get the current key. 3664bb42f2d1SToke Høiland-Jørgensen */ 3665bb42f2d1SToke Høiland-Jørgensen r = ieee80211_tx_h_select_key(&tx); 3666bb42f2d1SToke Høiland-Jørgensen if (r != TX_CONTINUE) { 3667bb42f2d1SToke Høiland-Jørgensen ieee80211_free_txskb(&local->hw, skb); 3668bb42f2d1SToke Høiland-Jørgensen goto begin; 3669bb42f2d1SToke Høiland-Jørgensen } 3670bb42f2d1SToke Høiland-Jørgensen 3671c1f4c9edSFelix Fietkau if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags)) 3672c1f4c9edSFelix Fietkau info->flags |= IEEE80211_TX_CTL_AMPDU; 3673c1f4c9edSFelix Fietkau else 3674c1f4c9edSFelix Fietkau info->flags &= ~IEEE80211_TX_CTL_AMPDU; 3675c1f4c9edSFelix Fietkau 3676cc20ff2cSFelix Fietkau if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) 367750ff477aSJohn Crispin goto encap_out; 367850ff477aSJohn Crispin 3679bb42f2d1SToke Høiland-Jørgensen if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) { 3680e0e2efffSToke Høiland-Jørgensen struct sta_info *sta = container_of(txq->sta, struct sta_info, 3681e0e2efffSToke Høiland-Jørgensen sta); 3682bb42f2d1SToke Høiland-Jørgensen u8 pn_offs = 0; 3683e0e2efffSToke Høiland-Jørgensen 3684bb42f2d1SToke Høiland-Jørgensen if (tx.key && 3685bb42f2d1SToke Høiland-Jørgensen (tx.key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) 3686bb42f2d1SToke Høiland-Jørgensen pn_offs = ieee80211_hdrlen(hdr->frame_control); 3687bb42f2d1SToke Høiland-Jørgensen 3688*03c3911dSRyder Lee r = ieee80211_xmit_fast_finish(sta->sdata, sta, pn_offs, 3689*03c3911dSRyder Lee tx.key, &tx); 3690*03c3911dSRyder Lee if (r != TX_CONTINUE) { 3691*03c3911dSRyder Lee ieee80211_free_txskb(&local->hw, skb); 3692*03c3911dSRyder Lee goto begin; 3693*03c3911dSRyder Lee } 3694bb42f2d1SToke Høiland-Jørgensen } else { 3695bb42f2d1SToke Høiland-Jørgensen if (invoke_tx_handlers_late(&tx)) 3696bb42f2d1SToke Høiland-Jørgensen goto begin; 3697bb42f2d1SToke Høiland-Jørgensen 3698bb42f2d1SToke Høiland-Jørgensen skb = __skb_dequeue(&tx.skbs); 3699bb42f2d1SToke Høiland-Jørgensen 3700ded4698bSFelix Fietkau if (!skb_queue_empty(&tx.skbs)) { 3701ded4698bSFelix Fietkau spin_lock_bh(&fq->lock); 3702bb42f2d1SToke Høiland-Jørgensen skb_queue_splice_tail(&tx.skbs, &txqi->frags); 3703ded4698bSFelix Fietkau spin_unlock_bh(&fq->lock); 3704ded4698bSFelix Fietkau } 3705e0e2efffSToke Høiland-Jørgensen } 3706e0e2efffSToke Høiland-Jørgensen 3707233e98dcSJohannes Berg if (skb_has_frag_list(skb) && 37081e1430d5SJohannes Berg !ieee80211_hw_check(&local->hw, TX_FRAG_LIST)) { 37091e1430d5SJohannes Berg if (skb_linearize(skb)) { 37101e1430d5SJohannes Berg ieee80211_free_txskb(&local->hw, skb); 37111e1430d5SJohannes Berg goto begin; 37121e1430d5SJohannes Berg } 37131e1430d5SJohannes Berg } 37141e1430d5SJohannes Berg 371553168215SJohannes Berg switch (tx.sdata->vif.type) { 371653168215SJohannes Berg case NL80211_IFTYPE_MONITOR: 371753168215SJohannes Berg if (tx.sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) { 371853168215SJohannes Berg vif = &tx.sdata->vif; 371953168215SJohannes Berg break; 372053168215SJohannes Berg } 372153168215SJohannes Berg tx.sdata = rcu_dereference(local->monitor_sdata); 372253168215SJohannes Berg if (tx.sdata) { 372353168215SJohannes Berg vif = &tx.sdata->vif; 372453168215SJohannes Berg info->hw_queue = 372553168215SJohannes Berg vif->hw_queue[skb_get_queue_mapping(skb)]; 372653168215SJohannes Berg } else if (ieee80211_hw_check(&local->hw, QUEUE_CONTROL)) { 372753168215SJohannes Berg ieee80211_free_txskb(&local->hw, skb); 372853168215SJohannes Berg goto begin; 372953168215SJohannes Berg } else { 373053168215SJohannes Berg vif = NULL; 373153168215SJohannes Berg } 373253168215SJohannes Berg break; 373353168215SJohannes Berg case NL80211_IFTYPE_AP_VLAN: 373453168215SJohannes Berg tx.sdata = container_of(tx.sdata->bss, 373553168215SJohannes Berg struct ieee80211_sub_if_data, u.ap); 3736fc0561dcSGustavo A. R. Silva fallthrough; 373753168215SJohannes Berg default: 373853168215SJohannes Berg vif = &tx.sdata->vif; 373953168215SJohannes Berg break; 374053168215SJohannes Berg } 374153168215SJohannes Berg 374250ff477aSJohn Crispin encap_out: 374353168215SJohannes Berg IEEE80211_SKB_CB(skb)->control.vif = vif; 37447a89233aSToke Høiland-Jørgensen 3745ca98c47dSJohannes Berg if (vif && 3746ca98c47dSJohannes Berg wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) { 37473ff901cbSFelix Fietkau bool ampdu = txq->ac != IEEE80211_AC_VO; 37487a89233aSToke Høiland-Jørgensen u32 airtime; 37497a89233aSToke Høiland-Jørgensen 37507a89233aSToke Høiland-Jørgensen airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta, 37513ff901cbSFelix Fietkau skb->len, ampdu); 37527a89233aSToke Høiland-Jørgensen if (airtime) { 37537a89233aSToke Høiland-Jørgensen airtime = ieee80211_info_set_tx_time_est(info, airtime); 37547a89233aSToke Høiland-Jørgensen ieee80211_sta_update_pending_airtime(local, tx.sta, 37557a89233aSToke Høiland-Jørgensen txq->ac, 37567a89233aSToke Høiland-Jørgensen airtime, 37577a89233aSToke Høiland-Jørgensen false); 37587a89233aSToke Høiland-Jørgensen } 37597a89233aSToke Høiland-Jørgensen } 37607a89233aSToke Høiland-Jørgensen 3761ded4698bSFelix Fietkau return skb; 376221a5d4c3SManikanta Pubbisetty 3763e0e2efffSToke Høiland-Jørgensen out: 3764e0e2efffSToke Høiland-Jørgensen spin_unlock_bh(&fq->lock); 3765e0e2efffSToke Høiland-Jørgensen 3766e0e2efffSToke Høiland-Jørgensen return skb; 3767e0e2efffSToke Høiland-Jørgensen } 3768e0e2efffSToke Høiland-Jørgensen EXPORT_SYMBOL(ieee80211_tx_dequeue); 3769e0e2efffSToke Høiland-Jørgensen 377018667600SToke Høiland-Jørgensen struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac) 377118667600SToke Høiland-Jørgensen { 377218667600SToke Høiland-Jørgensen struct ieee80211_local *local = hw_to_local(hw); 37735b989c18SFelix Fietkau struct ieee80211_txq *ret = NULL; 37743ace10f5SKan Yan struct txq_info *txqi = NULL, *head = NULL; 37753ace10f5SKan Yan bool found_eligible_txq = false; 377618667600SToke Høiland-Jørgensen 37775b989c18SFelix Fietkau spin_lock_bh(&local->active_txq_lock[ac]); 377818667600SToke Høiland-Jørgensen 3779b4809e94SToke Høiland-Jørgensen begin: 378018667600SToke Høiland-Jørgensen txqi = list_first_entry_or_null(&local->active_txqs[ac], 378118667600SToke Høiland-Jørgensen struct txq_info, 378218667600SToke Høiland-Jørgensen schedule_order); 3783b4809e94SToke Høiland-Jørgensen if (!txqi) 37845b989c18SFelix Fietkau goto out; 378518667600SToke Høiland-Jørgensen 37863ace10f5SKan Yan if (txqi == head) { 37873ace10f5SKan Yan if (!found_eligible_txq) 37883ace10f5SKan Yan goto out; 37893ace10f5SKan Yan else 37903ace10f5SKan Yan found_eligible_txq = false; 37913ace10f5SKan Yan } 37923ace10f5SKan Yan 37933ace10f5SKan Yan if (!head) 37943ace10f5SKan Yan head = txqi; 37953ace10f5SKan Yan 3796b4809e94SToke Høiland-Jørgensen if (txqi->txq.sta) { 3797b4809e94SToke Høiland-Jørgensen struct sta_info *sta = container_of(txqi->txq.sta, 3798b4809e94SToke Høiland-Jørgensen struct sta_info, sta); 37993ace10f5SKan Yan bool aql_check = ieee80211_txq_airtime_check(hw, &txqi->txq); 38003ace10f5SKan Yan s64 deficit = sta->airtime[txqi->txq.ac].deficit; 3801b4809e94SToke Høiland-Jørgensen 38023ace10f5SKan Yan if (aql_check) 38033ace10f5SKan Yan found_eligible_txq = true; 38043ace10f5SKan Yan 38053ace10f5SKan Yan if (deficit < 0) 3806b4809e94SToke Høiland-Jørgensen sta->airtime[txqi->txq.ac].deficit += 3807b4809e94SToke Høiland-Jørgensen sta->airtime_weight; 38083ace10f5SKan Yan 38093ace10f5SKan Yan if (deficit < 0 || !aql_check) { 3810b4809e94SToke Høiland-Jørgensen list_move_tail(&txqi->schedule_order, 3811b4809e94SToke Høiland-Jørgensen &local->active_txqs[txqi->txq.ac]); 3812b4809e94SToke Høiland-Jørgensen goto begin; 3813b4809e94SToke Høiland-Jørgensen } 3814b4809e94SToke Høiland-Jørgensen } 3815b4809e94SToke Høiland-Jørgensen 3816b4809e94SToke Høiland-Jørgensen 3817b4809e94SToke Høiland-Jørgensen if (txqi->schedule_round == local->schedule_round[ac]) 38185b989c18SFelix Fietkau goto out; 381918667600SToke Høiland-Jørgensen 382018667600SToke Høiland-Jørgensen list_del_init(&txqi->schedule_order); 382118667600SToke Høiland-Jørgensen txqi->schedule_round = local->schedule_round[ac]; 38225b989c18SFelix Fietkau ret = &txqi->txq; 38235b989c18SFelix Fietkau 38245b989c18SFelix Fietkau out: 38255b989c18SFelix Fietkau spin_unlock_bh(&local->active_txq_lock[ac]); 38265b989c18SFelix Fietkau return ret; 382718667600SToke Høiland-Jørgensen } 382818667600SToke Høiland-Jørgensen EXPORT_SYMBOL(ieee80211_next_txq); 382918667600SToke Høiland-Jørgensen 38302b4a6698SFelix Fietkau void __ieee80211_schedule_txq(struct ieee80211_hw *hw, 38312b4a6698SFelix Fietkau struct ieee80211_txq *txq, 38322b4a6698SFelix Fietkau bool force) 383318667600SToke Høiland-Jørgensen { 383418667600SToke Høiland-Jørgensen struct ieee80211_local *local = hw_to_local(hw); 383518667600SToke Høiland-Jørgensen struct txq_info *txqi = to_txq_info(txq); 383618667600SToke Høiland-Jørgensen 38375b989c18SFelix Fietkau spin_lock_bh(&local->active_txq_lock[txq->ac]); 383818667600SToke Høiland-Jørgensen 383918667600SToke Høiland-Jørgensen if (list_empty(&txqi->schedule_order) && 38402b4a6698SFelix Fietkau (force || !skb_queue_empty(&txqi->frags) || 38412b4a6698SFelix Fietkau txqi->tin.backlog_packets)) { 3842b4809e94SToke Høiland-Jørgensen /* If airtime accounting is active, always enqueue STAs at the 3843b4809e94SToke Høiland-Jørgensen * head of the list to ensure that they only get moved to the 3844b4809e94SToke Høiland-Jørgensen * back by the airtime DRR scheduler once they have a negative 3845b4809e94SToke Høiland-Jørgensen * deficit. A station that already has a negative deficit will 3846b4809e94SToke Høiland-Jørgensen * get immediately moved to the back of the list on the next 3847b4809e94SToke Høiland-Jørgensen * call to ieee80211_next_txq(). 3848b4809e94SToke Høiland-Jørgensen */ 3849c13cf5c1SLorenzo Bianconi if (txqi->txq.sta && local->airtime_flags && 3850b4809e94SToke Høiland-Jørgensen wiphy_ext_feature_isset(local->hw.wiphy, 3851b4809e94SToke Høiland-Jørgensen NL80211_EXT_FEATURE_AIRTIME_FAIRNESS)) 3852b4809e94SToke Høiland-Jørgensen list_add(&txqi->schedule_order, 3853b4809e94SToke Høiland-Jørgensen &local->active_txqs[txq->ac]); 3854b4809e94SToke Høiland-Jørgensen else 385518667600SToke Høiland-Jørgensen list_add_tail(&txqi->schedule_order, 385618667600SToke Høiland-Jørgensen &local->active_txqs[txq->ac]); 385718667600SToke Høiland-Jørgensen } 385818667600SToke Høiland-Jørgensen 3859390298e8SToke Høiland-Jørgensen spin_unlock_bh(&local->active_txq_lock[txq->ac]); 3860390298e8SToke Høiland-Jørgensen } 38612b4a6698SFelix Fietkau EXPORT_SYMBOL(__ieee80211_schedule_txq); 3862390298e8SToke Høiland-Jørgensen 3863e908435eSLorenzo Bianconi DEFINE_STATIC_KEY_FALSE(aql_disable); 3864e908435eSLorenzo Bianconi 38653ace10f5SKan Yan bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw, 38663ace10f5SKan Yan struct ieee80211_txq *txq) 38673ace10f5SKan Yan { 38683ace10f5SKan Yan struct sta_info *sta; 38693ace10f5SKan Yan struct ieee80211_local *local = hw_to_local(hw); 38703ace10f5SKan Yan 3871911bde0fSToke Høiland-Jørgensen if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) 38723ace10f5SKan Yan return true; 38733ace10f5SKan Yan 3874e908435eSLorenzo Bianconi if (static_branch_unlikely(&aql_disable)) 3875e908435eSLorenzo Bianconi return true; 3876e908435eSLorenzo Bianconi 38773ace10f5SKan Yan if (!txq->sta) 38783ace10f5SKan Yan return true; 38793ace10f5SKan Yan 388073bc9e0aSJohannes Berg if (unlikely(txq->tid == IEEE80211_NUM_TIDS)) 388173bc9e0aSJohannes Berg return true; 388273bc9e0aSJohannes Berg 38833ace10f5SKan Yan sta = container_of(txq->sta, struct sta_info, sta); 38843ace10f5SKan Yan if (atomic_read(&sta->airtime[txq->ac].aql_tx_pending) < 38853ace10f5SKan Yan sta->airtime[txq->ac].aql_limit_low) 38863ace10f5SKan Yan return true; 38873ace10f5SKan Yan 38883ace10f5SKan Yan if (atomic_read(&local->aql_total_pending_airtime) < 38893ace10f5SKan Yan local->aql_threshold && 38903ace10f5SKan Yan atomic_read(&sta->airtime[txq->ac].aql_tx_pending) < 38913ace10f5SKan Yan sta->airtime[txq->ac].aql_limit_high) 38923ace10f5SKan Yan return true; 38933ace10f5SKan Yan 38943ace10f5SKan Yan return false; 38953ace10f5SKan Yan } 38963ace10f5SKan Yan EXPORT_SYMBOL(ieee80211_txq_airtime_check); 38973ace10f5SKan Yan 3898b4809e94SToke Høiland-Jørgensen bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw, 3899b4809e94SToke Høiland-Jørgensen struct ieee80211_txq *txq) 3900b4809e94SToke Høiland-Jørgensen { 3901b4809e94SToke Høiland-Jørgensen struct ieee80211_local *local = hw_to_local(hw); 3902b4809e94SToke Høiland-Jørgensen struct txq_info *iter, *tmp, *txqi = to_txq_info(txq); 3903b4809e94SToke Høiland-Jørgensen struct sta_info *sta; 3904b4809e94SToke Høiland-Jørgensen u8 ac = txq->ac; 3905b4809e94SToke Høiland-Jørgensen 39065b989c18SFelix Fietkau spin_lock_bh(&local->active_txq_lock[ac]); 3907b4809e94SToke Høiland-Jørgensen 3908b4809e94SToke Høiland-Jørgensen if (!txqi->txq.sta) 3909b4809e94SToke Høiland-Jørgensen goto out; 3910b4809e94SToke Høiland-Jørgensen 3911b4809e94SToke Høiland-Jørgensen if (list_empty(&txqi->schedule_order)) 3912b4809e94SToke Høiland-Jørgensen goto out; 3913b4809e94SToke Høiland-Jørgensen 3914b4809e94SToke Høiland-Jørgensen list_for_each_entry_safe(iter, tmp, &local->active_txqs[ac], 3915b4809e94SToke Høiland-Jørgensen schedule_order) { 3916b4809e94SToke Høiland-Jørgensen if (iter == txqi) 3917b4809e94SToke Høiland-Jørgensen break; 3918b4809e94SToke Høiland-Jørgensen 3919b4809e94SToke Høiland-Jørgensen if (!iter->txq.sta) { 3920b4809e94SToke Høiland-Jørgensen list_move_tail(&iter->schedule_order, 3921b4809e94SToke Høiland-Jørgensen &local->active_txqs[ac]); 3922b4809e94SToke Høiland-Jørgensen continue; 3923b4809e94SToke Høiland-Jørgensen } 3924b4809e94SToke Høiland-Jørgensen sta = container_of(iter->txq.sta, struct sta_info, sta); 3925b4809e94SToke Høiland-Jørgensen if (sta->airtime[ac].deficit < 0) 3926b4809e94SToke Høiland-Jørgensen sta->airtime[ac].deficit += sta->airtime_weight; 3927b4809e94SToke Høiland-Jørgensen list_move_tail(&iter->schedule_order, &local->active_txqs[ac]); 3928b4809e94SToke Høiland-Jørgensen } 3929b4809e94SToke Høiland-Jørgensen 3930b4809e94SToke Høiland-Jørgensen sta = container_of(txqi->txq.sta, struct sta_info, sta); 3931b4809e94SToke Høiland-Jørgensen if (sta->airtime[ac].deficit >= 0) 3932b4809e94SToke Høiland-Jørgensen goto out; 3933b4809e94SToke Høiland-Jørgensen 3934b4809e94SToke Høiland-Jørgensen sta->airtime[ac].deficit += sta->airtime_weight; 3935b4809e94SToke Høiland-Jørgensen list_move_tail(&txqi->schedule_order, &local->active_txqs[ac]); 39365b989c18SFelix Fietkau spin_unlock_bh(&local->active_txq_lock[ac]); 3937b4809e94SToke Høiland-Jørgensen 3938b4809e94SToke Høiland-Jørgensen return false; 3939b4809e94SToke Høiland-Jørgensen out: 3940b4809e94SToke Høiland-Jørgensen if (!list_empty(&txqi->schedule_order)) 3941b4809e94SToke Høiland-Jørgensen list_del_init(&txqi->schedule_order); 39425b989c18SFelix Fietkau spin_unlock_bh(&local->active_txq_lock[ac]); 3943b4809e94SToke Høiland-Jørgensen 3944b4809e94SToke Høiland-Jørgensen return true; 3945b4809e94SToke Høiland-Jørgensen } 3946b4809e94SToke Høiland-Jørgensen EXPORT_SYMBOL(ieee80211_txq_may_transmit); 3947b4809e94SToke Høiland-Jørgensen 394818667600SToke Høiland-Jørgensen void ieee80211_txq_schedule_start(struct ieee80211_hw *hw, u8 ac) 394918667600SToke Høiland-Jørgensen { 395018667600SToke Høiland-Jørgensen struct ieee80211_local *local = hw_to_local(hw); 395118667600SToke Høiland-Jørgensen 395218667600SToke Høiland-Jørgensen spin_lock_bh(&local->active_txq_lock[ac]); 395318667600SToke Høiland-Jørgensen local->schedule_round[ac]++; 395418667600SToke Høiland-Jørgensen spin_unlock_bh(&local->active_txq_lock[ac]); 395518667600SToke Høiland-Jørgensen } 39565b989c18SFelix Fietkau EXPORT_SYMBOL(ieee80211_txq_schedule_start); 395718667600SToke Høiland-Jørgensen 395808a46c64SFelix Fietkau static void 395908a46c64SFelix Fietkau ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata, 396008a46c64SFelix Fietkau struct sta_info *sta, 396108a46c64SFelix Fietkau struct sk_buff *skb) 396208a46c64SFelix Fietkau { 396308a46c64SFelix Fietkau struct rate_control_ref *ref = sdata->local->rate_ctrl; 396408a46c64SFelix Fietkau u16 tid; 396508a46c64SFelix Fietkau 396608a46c64SFelix Fietkau if (!ref || !(ref->ops->capa & RATE_CTRL_CAPA_AMPDU_TRIGGER)) 396708a46c64SFelix Fietkau return; 396808a46c64SFelix Fietkau 396908a46c64SFelix Fietkau if (!sta || !sta->sta.ht_cap.ht_supported || 397008a46c64SFelix Fietkau !sta->sta.wme || skb_get_queue_mapping(skb) == IEEE80211_AC_VO || 397108a46c64SFelix Fietkau skb->protocol == sdata->control_port_protocol) 397208a46c64SFelix Fietkau return; 397308a46c64SFelix Fietkau 397408a46c64SFelix Fietkau tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; 397508a46c64SFelix Fietkau if (likely(sta->ampdu_mlme.tid_tx[tid])) 397608a46c64SFelix Fietkau return; 397708a46c64SFelix Fietkau 397808a46c64SFelix Fietkau ieee80211_start_tx_ba_session(&sta->sta, tid, 0); 397908a46c64SFelix Fietkau } 398008a46c64SFelix Fietkau 39814c9451edSJohannes Berg void __ieee80211_subif_start_xmit(struct sk_buff *skb, 39824c9451edSJohannes Berg struct net_device *dev, 398306016772SRajkumar Manoharan u32 info_flags, 3984a7528198SMarkus Theil u32 ctrl_flags, 3985a7528198SMarkus Theil u64 *cookie) 39864c9451edSJohannes Berg { 39874c9451edSJohannes Berg struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 39881974da8bSFelix Fietkau struct ieee80211_local *local = sdata->local; 398997ffe757SJohannes Berg struct sta_info *sta; 399080616c0dSJohannes Berg struct sk_buff *next; 39914c9451edSJohannes Berg 39924c9451edSJohannes Berg if (unlikely(skb->len < ETH_HLEN)) { 39934c9451edSJohannes Berg kfree_skb(skb); 39944c9451edSJohannes Berg return; 39954c9451edSJohannes Berg } 39964c9451edSJohannes Berg 39974c9451edSJohannes Berg rcu_read_lock(); 39984c9451edSJohannes Berg 39992d981fddSJohannes Berg if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) 40002d981fddSJohannes Berg goto out_free; 40014c9451edSJohannes Berg 40021974da8bSFelix Fietkau if (IS_ERR(sta)) 40031974da8bSFelix Fietkau sta = NULL; 40041974da8bSFelix Fietkau 40051974da8bSFelix Fietkau if (local->ops->wake_tx_queue) { 40061974da8bSFelix Fietkau u16 queue = __ieee80211_select_queue(sdata, sta, skb); 40071974da8bSFelix Fietkau skb_set_queue_mapping(skb, queue); 4008180ac48eSFelix Fietkau skb_get_hash(skb); 40091974da8bSFelix Fietkau } 40101974da8bSFelix Fietkau 401108a46c64SFelix Fietkau ieee80211_aggr_check(sdata, sta, skb); 401208a46c64SFelix Fietkau 40131974da8bSFelix Fietkau if (sta) { 401417c18bf8SJohannes Berg struct ieee80211_fast_tx *fast_tx; 401517c18bf8SJohannes Berg 401670e53669SWen Gong sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift); 401736148c2bSToke Høiland-Jørgensen 401817c18bf8SJohannes Berg fast_tx = rcu_dereference(sta->fast_tx); 401917c18bf8SJohannes Berg 402017c18bf8SJohannes Berg if (fast_tx && 4021bb42f2d1SToke Høiland-Jørgensen ieee80211_xmit_fast(sdata, sta, fast_tx, skb)) 402217c18bf8SJohannes Berg goto out; 402317c18bf8SJohannes Berg } 402417c18bf8SJohannes Berg 402580616c0dSJohannes Berg if (skb_is_gso(skb)) { 402680616c0dSJohannes Berg struct sk_buff *segs; 402780616c0dSJohannes Berg 402880616c0dSJohannes Berg segs = skb_gso_segment(skb, 0); 402980616c0dSJohannes Berg if (IS_ERR(segs)) { 403080616c0dSJohannes Berg goto out_free; 403180616c0dSJohannes Berg } else if (segs) { 403280616c0dSJohannes Berg consume_skb(skb); 403380616c0dSJohannes Berg skb = segs; 403480616c0dSJohannes Berg } 403580616c0dSJohannes Berg } else { 4036680a0dabSJohannes Berg /* we cannot process non-linear frames on this path */ 4037680a0dabSJohannes Berg if (skb_linearize(skb)) { 4038680a0dabSJohannes Berg kfree_skb(skb); 4039680a0dabSJohannes Berg goto out; 4040680a0dabSJohannes Berg } 4041680a0dabSJohannes Berg 404280616c0dSJohannes Berg /* the frame could be fragmented, software-encrypted, and other 404380616c0dSJohannes Berg * things so we cannot really handle checksum offload with it - 404480616c0dSJohannes Berg * fix it up in software before we handle anything else. 40452d981fddSJohannes Berg */ 40462d981fddSJohannes Berg if (skb->ip_summed == CHECKSUM_PARTIAL) { 40472d981fddSJohannes Berg skb_set_transport_header(skb, 40482d981fddSJohannes Berg skb_checksum_start_offset(skb)); 40492d981fddSJohannes Berg if (skb_checksum_help(skb)) 40502d981fddSJohannes Berg goto out_free; 40512d981fddSJohannes Berg } 405280616c0dSJohannes Berg } 405380616c0dSJohannes Berg 40549f3ef3d7SJason A. Donenfeld skb_list_walk_safe(skb, skb, next) { 40559f3ef3d7SJason A. Donenfeld skb_mark_not_on_list(skb); 40562d981fddSJohannes Berg 40575af7fef3SMarkus Theil if (skb->protocol == sdata->control_port_protocol) 40585af7fef3SMarkus Theil ctrl_flags |= IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP; 40595af7fef3SMarkus Theil 406006016772SRajkumar Manoharan skb = ieee80211_build_hdr(sdata, skb, info_flags, 4061a7528198SMarkus Theil sta, ctrl_flags, cookie); 40629f3ef3d7SJason A. Donenfeld if (IS_ERR(skb)) { 40639f3ef3d7SJason A. Donenfeld kfree_skb_list(next); 40644c9451edSJohannes Berg goto out; 40659f3ef3d7SJason A. Donenfeld } 40664c9451edSJohannes Berg 406736ec144fSLev Stipakov dev_sw_netstats_tx_add(dev, 1, skb->len); 40684c9451edSJohannes Berg 406908aca29aSMathy Vanhoef ieee80211_xmit(sdata, sta, skb); 407080616c0dSJohannes Berg } 40712d981fddSJohannes Berg goto out; 40722d981fddSJohannes Berg out_free: 40732d981fddSJohannes Berg kfree_skb(skb); 40744c9451edSJohannes Berg out: 40754c9451edSJohannes Berg rcu_read_unlock(); 40764c9451edSJohannes Berg } 40774c9451edSJohannes Berg 4078ebceec86SMichael Braun static int ieee80211_change_da(struct sk_buff *skb, struct sta_info *sta) 4079ebceec86SMichael Braun { 4080ebceec86SMichael Braun struct ethhdr *eth; 4081ebceec86SMichael Braun int err; 4082ebceec86SMichael Braun 4083ebceec86SMichael Braun err = skb_ensure_writable(skb, ETH_HLEN); 4084ebceec86SMichael Braun if (unlikely(err)) 4085ebceec86SMichael Braun return err; 4086ebceec86SMichael Braun 4087ebceec86SMichael Braun eth = (void *)skb->data; 4088ebceec86SMichael Braun ether_addr_copy(eth->h_dest, sta->sta.addr); 4089ebceec86SMichael Braun 4090ebceec86SMichael Braun return 0; 4091ebceec86SMichael Braun } 4092ebceec86SMichael Braun 4093ebceec86SMichael Braun static bool ieee80211_multicast_to_unicast(struct sk_buff *skb, 4094ebceec86SMichael Braun struct net_device *dev) 4095ebceec86SMichael Braun { 4096ebceec86SMichael Braun struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 4097ebceec86SMichael Braun const struct ethhdr *eth = (void *)skb->data; 4098ebceec86SMichael Braun const struct vlan_ethhdr *ethvlan = (void *)skb->data; 4099ebceec86SMichael Braun __be16 ethertype; 4100ebceec86SMichael Braun 4101ebceec86SMichael Braun if (likely(!is_multicast_ether_addr(eth->h_dest))) 4102ebceec86SMichael Braun return false; 4103ebceec86SMichael Braun 4104ebceec86SMichael Braun switch (sdata->vif.type) { 4105ebceec86SMichael Braun case NL80211_IFTYPE_AP_VLAN: 4106ebceec86SMichael Braun if (sdata->u.vlan.sta) 4107ebceec86SMichael Braun return false; 4108ebceec86SMichael Braun if (sdata->wdev.use_4addr) 4109ebceec86SMichael Braun return false; 4110fc0561dcSGustavo A. R. Silva fallthrough; 4111ebceec86SMichael Braun case NL80211_IFTYPE_AP: 4112ebceec86SMichael Braun /* check runtime toggle for this bss */ 4113ebceec86SMichael Braun if (!sdata->bss->multicast_to_unicast) 4114ebceec86SMichael Braun return false; 4115ebceec86SMichael Braun break; 4116ebceec86SMichael Braun default: 4117ebceec86SMichael Braun return false; 4118ebceec86SMichael Braun } 4119ebceec86SMichael Braun 4120ebceec86SMichael Braun /* multicast to unicast conversion only for some payload */ 4121ebceec86SMichael Braun ethertype = eth->h_proto; 4122ebceec86SMichael Braun if (ethertype == htons(ETH_P_8021Q) && skb->len >= VLAN_ETH_HLEN) 4123ebceec86SMichael Braun ethertype = ethvlan->h_vlan_encapsulated_proto; 4124ebceec86SMichael Braun switch (ethertype) { 4125ebceec86SMichael Braun case htons(ETH_P_ARP): 4126ebceec86SMichael Braun case htons(ETH_P_IP): 4127ebceec86SMichael Braun case htons(ETH_P_IPV6): 4128ebceec86SMichael Braun break; 4129ebceec86SMichael Braun default: 4130ebceec86SMichael Braun return false; 4131ebceec86SMichael Braun } 4132ebceec86SMichael Braun 4133ebceec86SMichael Braun return true; 4134ebceec86SMichael Braun } 4135ebceec86SMichael Braun 4136ebceec86SMichael Braun static void 4137ebceec86SMichael Braun ieee80211_convert_to_unicast(struct sk_buff *skb, struct net_device *dev, 4138ebceec86SMichael Braun struct sk_buff_head *queue) 4139ebceec86SMichael Braun { 4140ebceec86SMichael Braun struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 4141ebceec86SMichael Braun struct ieee80211_local *local = sdata->local; 4142ebceec86SMichael Braun const struct ethhdr *eth = (struct ethhdr *)skb->data; 4143ebceec86SMichael Braun struct sta_info *sta, *first = NULL; 4144ebceec86SMichael Braun struct sk_buff *cloned_skb; 4145ebceec86SMichael Braun 4146ebceec86SMichael Braun rcu_read_lock(); 4147ebceec86SMichael Braun 4148ebceec86SMichael Braun list_for_each_entry_rcu(sta, &local->sta_list, list) { 4149ebceec86SMichael Braun if (sdata != sta->sdata) 4150ebceec86SMichael Braun /* AP-VLAN mismatch */ 4151ebceec86SMichael Braun continue; 4152ebceec86SMichael Braun if (unlikely(ether_addr_equal(eth->h_source, sta->sta.addr))) 4153ebceec86SMichael Braun /* do not send back to source */ 4154ebceec86SMichael Braun continue; 4155ebceec86SMichael Braun if (!first) { 4156ebceec86SMichael Braun first = sta; 4157ebceec86SMichael Braun continue; 4158ebceec86SMichael Braun } 4159ebceec86SMichael Braun cloned_skb = skb_clone(skb, GFP_ATOMIC); 4160ebceec86SMichael Braun if (!cloned_skb) 4161ebceec86SMichael Braun goto multicast; 4162ebceec86SMichael Braun if (unlikely(ieee80211_change_da(cloned_skb, sta))) { 4163ebceec86SMichael Braun dev_kfree_skb(cloned_skb); 4164ebceec86SMichael Braun goto multicast; 4165ebceec86SMichael Braun } 4166ebceec86SMichael Braun __skb_queue_tail(queue, cloned_skb); 4167ebceec86SMichael Braun } 4168ebceec86SMichael Braun 4169ebceec86SMichael Braun if (likely(first)) { 4170ebceec86SMichael Braun if (unlikely(ieee80211_change_da(skb, first))) 4171ebceec86SMichael Braun goto multicast; 4172ebceec86SMichael Braun __skb_queue_tail(queue, skb); 4173ebceec86SMichael Braun } else { 4174ebceec86SMichael Braun /* no STA connected, drop */ 4175ebceec86SMichael Braun kfree_skb(skb); 4176ebceec86SMichael Braun skb = NULL; 4177ebceec86SMichael Braun } 4178ebceec86SMichael Braun 4179ebceec86SMichael Braun goto out; 4180ebceec86SMichael Braun multicast: 4181ebceec86SMichael Braun __skb_queue_purge(queue); 4182ebceec86SMichael Braun __skb_queue_tail(queue, skb); 4183ebceec86SMichael Braun out: 4184ebceec86SMichael Braun rcu_read_unlock(); 4185ebceec86SMichael Braun } 4186ebceec86SMichael Braun 41874c9451edSJohannes Berg /** 41884c9451edSJohannes Berg * ieee80211_subif_start_xmit - netif start_xmit function for 802.3 vifs 41894c9451edSJohannes Berg * @skb: packet to be sent 41904c9451edSJohannes Berg * @dev: incoming interface 41914c9451edSJohannes Berg * 41924c9451edSJohannes Berg * On failure skb will be freed. 41934c9451edSJohannes Berg */ 419424d342c5SLiad Kaufman netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, 419524d342c5SLiad Kaufman struct net_device *dev) 419624d342c5SLiad Kaufman { 4197ebceec86SMichael Braun if (unlikely(ieee80211_multicast_to_unicast(skb, dev))) { 4198ebceec86SMichael Braun struct sk_buff_head queue; 4199ebceec86SMichael Braun 4200ebceec86SMichael Braun __skb_queue_head_init(&queue); 4201ebceec86SMichael Braun ieee80211_convert_to_unicast(skb, dev, &queue); 4202ebceec86SMichael Braun while ((skb = __skb_dequeue(&queue))) 4203a7528198SMarkus Theil __ieee80211_subif_start_xmit(skb, dev, 0, 0, NULL); 4204ebceec86SMichael Braun } else { 4205a7528198SMarkus Theil __ieee80211_subif_start_xmit(skb, dev, 0, 0, NULL); 4206ebceec86SMichael Braun } 4207ebceec86SMichael Braun 420824d342c5SLiad Kaufman return NETDEV_TX_OK; 420924d342c5SLiad Kaufman } 4210e2ebc74dSJohannes Berg 421150ff477aSJohn Crispin static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata, 421250ff477aSJohn Crispin struct sk_buff *skb, int led_len, 421350ff477aSJohn Crispin struct sta_info *sta, 421450ff477aSJohn Crispin bool txpending) 421550ff477aSJohn Crispin { 421650ff477aSJohn Crispin struct ieee80211_local *local = sdata->local; 421750ff477aSJohn Crispin struct ieee80211_tx_control control = {}; 421850ff477aSJohn Crispin struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 421950ff477aSJohn Crispin struct ieee80211_sta *pubsta = NULL; 422050ff477aSJohn Crispin unsigned long flags; 422150ff477aSJohn Crispin int q = info->hw_queue; 422250ff477aSJohn Crispin 4223196900fdSLorenzo Bianconi if (sta) 4224196900fdSLorenzo Bianconi sk_pacing_shift_update(skb->sk, local->hw.tx_sk_pacing_shift); 4225196900fdSLorenzo Bianconi 422650ff477aSJohn Crispin if (ieee80211_queue_skb(local, sdata, sta, skb)) 422750ff477aSJohn Crispin return true; 422850ff477aSJohn Crispin 422950ff477aSJohn Crispin spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 423050ff477aSJohn Crispin 423150ff477aSJohn Crispin if (local->queue_stop_reasons[q] || 423250ff477aSJohn Crispin (!txpending && !skb_queue_empty(&local->pending[q]))) { 423350ff477aSJohn Crispin if (txpending) 423450ff477aSJohn Crispin skb_queue_head(&local->pending[q], skb); 423550ff477aSJohn Crispin else 423650ff477aSJohn Crispin skb_queue_tail(&local->pending[q], skb); 423750ff477aSJohn Crispin 423850ff477aSJohn Crispin spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 423950ff477aSJohn Crispin 424050ff477aSJohn Crispin return false; 424150ff477aSJohn Crispin } 424250ff477aSJohn Crispin 424350ff477aSJohn Crispin spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 424450ff477aSJohn Crispin 424550ff477aSJohn Crispin if (sta && sta->uploaded) 424650ff477aSJohn Crispin pubsta = &sta->sta; 424750ff477aSJohn Crispin 424850ff477aSJohn Crispin control.sta = pubsta; 424950ff477aSJohn Crispin 425050ff477aSJohn Crispin drv_tx(local, &control, skb); 425150ff477aSJohn Crispin 425250ff477aSJohn Crispin return true; 425350ff477aSJohn Crispin } 425450ff477aSJohn Crispin 425550ff477aSJohn Crispin static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata, 425650ff477aSJohn Crispin struct net_device *dev, struct sta_info *sta, 42576aea26ceSFelix Fietkau struct ieee80211_key *key, struct sk_buff *skb) 425850ff477aSJohn Crispin { 425950ff477aSJohn Crispin struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 426050ff477aSJohn Crispin struct ieee80211_local *local = sdata->local; 426196ae9cd0SFelix Fietkau struct tid_ampdu_tx *tid_tx; 426296ae9cd0SFelix Fietkau u8 tid; 426350ff477aSJohn Crispin 42645f8d69eaSFelix Fietkau if (local->ops->wake_tx_queue) { 42655f8d69eaSFelix Fietkau u16 queue = __ieee80211_select_queue(sdata, sta, skb); 42665f8d69eaSFelix Fietkau skb_set_queue_mapping(skb, queue); 42675f8d69eaSFelix Fietkau skb_get_hash(skb); 42685f8d69eaSFelix Fietkau } 42695f8d69eaSFelix Fietkau 427050ff477aSJohn Crispin if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) && 427150ff477aSJohn Crispin test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) 427250ff477aSJohn Crispin goto out_free; 427350ff477aSJohn Crispin 4274e61fbfcaSVasanthakumar Thiagarajan memset(info, 0, sizeof(*info)); 4275e61fbfcaSVasanthakumar Thiagarajan 427608a46c64SFelix Fietkau ieee80211_aggr_check(sdata, sta, skb); 427708a46c64SFelix Fietkau 427896ae9cd0SFelix Fietkau tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; 427996ae9cd0SFelix Fietkau tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]); 428096ae9cd0SFelix Fietkau if (tid_tx) { 428196ae9cd0SFelix Fietkau if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) { 428296ae9cd0SFelix Fietkau /* fall back to non-offload slow path */ 428396ae9cd0SFelix Fietkau __ieee80211_subif_start_xmit(skb, dev, 0, 0, NULL); 428496ae9cd0SFelix Fietkau return; 428596ae9cd0SFelix Fietkau } 428696ae9cd0SFelix Fietkau 428796ae9cd0SFelix Fietkau info->flags |= IEEE80211_TX_CTL_AMPDU; 428896ae9cd0SFelix Fietkau if (tid_tx->timeout) 428996ae9cd0SFelix Fietkau tid_tx->last_tx = jiffies; 429096ae9cd0SFelix Fietkau } 429196ae9cd0SFelix Fietkau 4292aea6a3f0SFelix Fietkau if (unlikely(skb->sk && 429350ff477aSJohn Crispin skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)) 4294e61fbfcaSVasanthakumar Thiagarajan info->ack_frame_id = ieee80211_store_ack_skb(local, skb, 4295e61fbfcaSVasanthakumar Thiagarajan &info->flags, NULL); 429650ff477aSJohn Crispin 429750ff477aSJohn Crispin info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)]; 429850ff477aSJohn Crispin 429936ec144fSLev Stipakov dev_sw_netstats_tx_add(dev, 1, skb->len); 430050ff477aSJohn Crispin 430150ff477aSJohn Crispin sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len; 430250ff477aSJohn Crispin sta->tx_stats.packets[skb_get_queue_mapping(skb)]++; 430350ff477aSJohn Crispin 430450ff477aSJohn Crispin if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 430550ff477aSJohn Crispin sdata = container_of(sdata->bss, 430650ff477aSJohn Crispin struct ieee80211_sub_if_data, u.ap); 430750ff477aSJohn Crispin 4308cc20ff2cSFelix Fietkau info->flags |= IEEE80211_TX_CTL_HW_80211_ENCAP; 430950ff477aSJohn Crispin info->control.vif = &sdata->vif; 431050ff477aSJohn Crispin 4311ae045152SFelix Fietkau if (key) 4312ae045152SFelix Fietkau info->control.hw_key = &key->conf; 4313ae045152SFelix Fietkau 431450ff477aSJohn Crispin ieee80211_tx_8023(sdata, skb, skb->len, sta, false); 431550ff477aSJohn Crispin 431650ff477aSJohn Crispin return; 431750ff477aSJohn Crispin 431850ff477aSJohn Crispin out_free: 431950ff477aSJohn Crispin kfree_skb(skb); 432050ff477aSJohn Crispin } 432150ff477aSJohn Crispin 432250ff477aSJohn Crispin netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb, 432350ff477aSJohn Crispin struct net_device *dev) 432450ff477aSJohn Crispin { 432550ff477aSJohn Crispin struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 4326aea6a3f0SFelix Fietkau struct ethhdr *ehdr = (struct ethhdr *)skb->data; 43276aea26ceSFelix Fietkau struct ieee80211_key *key; 432850ff477aSJohn Crispin struct sta_info *sta; 432950ff477aSJohn Crispin 433050ff477aSJohn Crispin if (unlikely(skb->len < ETH_HLEN)) { 433150ff477aSJohn Crispin kfree_skb(skb); 433250ff477aSJohn Crispin return NETDEV_TX_OK; 433350ff477aSJohn Crispin } 433450ff477aSJohn Crispin 433550ff477aSJohn Crispin rcu_read_lock(); 433650ff477aSJohn Crispin 43376aea26ceSFelix Fietkau if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) { 433850ff477aSJohn Crispin kfree_skb(skb); 43396aea26ceSFelix Fietkau goto out; 43406aea26ceSFelix Fietkau } 43416aea26ceSFelix Fietkau 43426aea26ceSFelix Fietkau if (unlikely(IS_ERR_OR_NULL(sta) || !sta->uploaded || 4343aea6a3f0SFelix Fietkau !test_sta_flag(sta, WLAN_STA_AUTHORIZED) || 4344aea6a3f0SFelix Fietkau sdata->control_port_protocol == ehdr->h_proto)) 4345b101dd2dSFelix Fietkau goto skip_offload; 4346b101dd2dSFelix Fietkau 4347b101dd2dSFelix Fietkau key = rcu_dereference(sta->ptk[sta->ptk_idx]); 4348b101dd2dSFelix Fietkau if (!key) 4349b101dd2dSFelix Fietkau key = rcu_dereference(sdata->default_unicast_key); 4350b101dd2dSFelix Fietkau 4351b101dd2dSFelix Fietkau if (key && (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) || 43526aea26ceSFelix Fietkau key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)) 4353b101dd2dSFelix Fietkau goto skip_offload; 435450ff477aSJohn Crispin 43556aea26ceSFelix Fietkau ieee80211_8023_xmit(sdata, dev, sta, key, skb); 4356b101dd2dSFelix Fietkau goto out; 43576aea26ceSFelix Fietkau 4358b101dd2dSFelix Fietkau skip_offload: 4359b101dd2dSFelix Fietkau ieee80211_subif_start_xmit(skb, dev); 43606aea26ceSFelix Fietkau out: 436150ff477aSJohn Crispin rcu_read_unlock(); 436250ff477aSJohn Crispin 436350ff477aSJohn Crispin return NETDEV_TX_OK; 436450ff477aSJohn Crispin } 436550ff477aSJohn Crispin 43667528ec57SJohannes Berg struct sk_buff * 43677528ec57SJohannes Berg ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata, 43687528ec57SJohannes Berg struct sk_buff *skb, u32 info_flags) 43697528ec57SJohannes Berg { 43707528ec57SJohannes Berg struct ieee80211_hdr *hdr; 43717528ec57SJohannes Berg struct ieee80211_tx_data tx = { 43727528ec57SJohannes Berg .local = sdata->local, 43737528ec57SJohannes Berg .sdata = sdata, 43747528ec57SJohannes Berg }; 437597ffe757SJohannes Berg struct sta_info *sta; 43767528ec57SJohannes Berg 43777528ec57SJohannes Berg rcu_read_lock(); 43787528ec57SJohannes Berg 437997ffe757SJohannes Berg if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) { 438097ffe757SJohannes Berg kfree_skb(skb); 438197ffe757SJohannes Berg skb = ERR_PTR(-EINVAL); 438297ffe757SJohannes Berg goto out; 438397ffe757SJohannes Berg } 438497ffe757SJohannes Berg 4385a7528198SMarkus Theil skb = ieee80211_build_hdr(sdata, skb, info_flags, sta, 0, NULL); 43867528ec57SJohannes Berg if (IS_ERR(skb)) 43877528ec57SJohannes Berg goto out; 43887528ec57SJohannes Berg 43897528ec57SJohannes Berg hdr = (void *)skb->data; 43907528ec57SJohannes Berg tx.sta = sta_info_get(sdata, hdr->addr1); 43917528ec57SJohannes Berg tx.skb = skb; 43927528ec57SJohannes Berg 43937528ec57SJohannes Berg if (ieee80211_tx_h_select_key(&tx) != TX_CONTINUE) { 43947528ec57SJohannes Berg rcu_read_unlock(); 43957528ec57SJohannes Berg kfree_skb(skb); 43967528ec57SJohannes Berg return ERR_PTR(-EINVAL); 43977528ec57SJohannes Berg } 43987528ec57SJohannes Berg 43997528ec57SJohannes Berg out: 44007528ec57SJohannes Berg rcu_read_unlock(); 44017528ec57SJohannes Berg return skb; 44027528ec57SJohannes Berg } 44037528ec57SJohannes Berg 4404e2530083SJohannes Berg /* 4405e2530083SJohannes Berg * ieee80211_clear_tx_pending may not be called in a context where 4406e2530083SJohannes Berg * it is possible that it packets could come in again. 4407e2530083SJohannes Berg */ 4408e2ebc74dSJohannes Berg void ieee80211_clear_tx_pending(struct ieee80211_local *local) 4409e2ebc74dSJohannes Berg { 44101f98ab7fSFelix Fietkau struct sk_buff *skb; 44112de8e0d9SJohannes Berg int i; 4412e2ebc74dSJohannes Berg 44131f98ab7fSFelix Fietkau for (i = 0; i < local->hw.queues; i++) { 44141f98ab7fSFelix Fietkau while ((skb = skb_dequeue(&local->pending[i])) != NULL) 44151f98ab7fSFelix Fietkau ieee80211_free_txskb(&local->hw, skb); 44161f98ab7fSFelix Fietkau } 4417e2ebc74dSJohannes Berg } 4418e2ebc74dSJohannes Berg 44197bb45683SJohannes Berg /* 44207bb45683SJohannes Berg * Returns false if the frame couldn't be transmitted but was queued instead, 44217bb45683SJohannes Berg * which in this case means re-queued -- take as an indication to stop sending 44227bb45683SJohannes Berg * more pending frames. 44237bb45683SJohannes Berg */ 4424cd8ffc80SJohannes Berg static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, 4425cd8ffc80SJohannes Berg struct sk_buff *skb) 4426cd8ffc80SJohannes Berg { 4427cd8ffc80SJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 4428cd8ffc80SJohannes Berg struct ieee80211_sub_if_data *sdata; 4429cd8ffc80SJohannes Berg struct sta_info *sta; 4430cd8ffc80SJohannes Berg struct ieee80211_hdr *hdr; 44317bb45683SJohannes Berg bool result; 443255de908aSJohannes Berg struct ieee80211_chanctx_conf *chanctx_conf; 4433cd8ffc80SJohannes Berg 44345061b0c2SJohannes Berg sdata = vif_to_sdata(info->control.vif); 4435cd8ffc80SJohannes Berg 4436cc20ff2cSFelix Fietkau if (info->control.flags & IEEE80211_TX_INTCFL_NEED_TXPROCESSING) { 443755de908aSJohannes Berg chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 443855de908aSJohannes Berg if (unlikely(!chanctx_conf)) { 443955de908aSJohannes Berg dev_kfree_skb(skb); 444055de908aSJohannes Berg return true; 444155de908aSJohannes Berg } 444273c4e195SJohannes Berg info->band = chanctx_conf->def.chan->band; 444308aca29aSMathy Vanhoef result = ieee80211_tx(sdata, NULL, skb, true); 4444cc20ff2cSFelix Fietkau } else if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) { 444550ff477aSJohn Crispin if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) { 444650ff477aSJohn Crispin dev_kfree_skb(skb); 444750ff477aSJohn Crispin return true; 444850ff477aSJohn Crispin } 444950ff477aSJohn Crispin 445050ff477aSJohn Crispin if (IS_ERR(sta) || (sta && !sta->uploaded)) 445150ff477aSJohn Crispin sta = NULL; 445250ff477aSJohn Crispin 445350ff477aSJohn Crispin result = ieee80211_tx_8023(sdata, skb, skb->len, sta, true); 4454cd8ffc80SJohannes Berg } else { 4455252b86c4SJohannes Berg struct sk_buff_head skbs; 4456252b86c4SJohannes Berg 4457252b86c4SJohannes Berg __skb_queue_head_init(&skbs); 4458252b86c4SJohannes Berg __skb_queue_tail(&skbs, skb); 4459252b86c4SJohannes Berg 4460cd8ffc80SJohannes Berg hdr = (struct ieee80211_hdr *)skb->data; 4461abe60632SJohannes Berg sta = sta_info_get(sdata, hdr->addr1); 4462cd8ffc80SJohannes Berg 446374e4dbfdSJohannes Berg result = __ieee80211_tx(local, &skbs, skb->len, sta, true); 4464cd8ffc80SJohannes Berg } 4465cd8ffc80SJohannes Berg 4466cd8ffc80SJohannes Berg return result; 4467cd8ffc80SJohannes Berg } 4468cd8ffc80SJohannes Berg 4469e2530083SJohannes Berg /* 44703b8d81e0SJohannes Berg * Transmit all pending packets. Called from tasklet. 4471e2530083SJohannes Berg */ 4472da1cad73SAllen Pais void ieee80211_tx_pending(struct tasklet_struct *t) 4473e2ebc74dSJohannes Berg { 4474da1cad73SAllen Pais struct ieee80211_local *local = from_tasklet(local, t, 4475da1cad73SAllen Pais tx_pending_tasklet); 44762a577d98SJohannes Berg unsigned long flags; 4477cd8ffc80SJohannes Berg int i; 44783b8d81e0SJohannes Berg bool txok; 4479e2ebc74dSJohannes Berg 4480f0e72851SJohannes Berg rcu_read_lock(); 44812a577d98SJohannes Berg 44823b8d81e0SJohannes Berg spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 4483176be728SJohannes Berg for (i = 0; i < local->hw.queues; i++) { 44842a577d98SJohannes Berg /* 44852a577d98SJohannes Berg * If queue is stopped by something other than due to pending 44862a577d98SJohannes Berg * frames, or we have no pending frames, proceed to next queue. 44872a577d98SJohannes Berg */ 44883b8d81e0SJohannes Berg if (local->queue_stop_reasons[i] || 44892a577d98SJohannes Berg skb_queue_empty(&local->pending[i])) 4490e2ebc74dSJohannes Berg continue; 4491e2530083SJohannes Berg 44922a577d98SJohannes Berg while (!skb_queue_empty(&local->pending[i])) { 44933b8d81e0SJohannes Berg struct sk_buff *skb = __skb_dequeue(&local->pending[i]); 44945061b0c2SJohannes Berg struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 44955061b0c2SJohannes Berg 4496a7bc376cSJohannes Berg if (WARN_ON(!info->control.vif)) { 4497c3e7724bSFelix Fietkau ieee80211_free_txskb(&local->hw, skb); 4498a7bc376cSJohannes Berg continue; 4499a7bc376cSJohannes Berg } 4500a7bc376cSJohannes Berg 45013b8d81e0SJohannes Berg spin_unlock_irqrestore(&local->queue_stop_reason_lock, 45023b8d81e0SJohannes Berg flags); 45032a577d98SJohannes Berg 45043b8d81e0SJohannes Berg txok = ieee80211_tx_pending_skb(local, skb); 45053b8d81e0SJohannes Berg spin_lock_irqsave(&local->queue_stop_reason_lock, 45063b8d81e0SJohannes Berg flags); 45073b8d81e0SJohannes Berg if (!txok) 45082a577d98SJohannes Berg break; 4509e2ebc74dSJohannes Berg } 45107236fe29SJohannes Berg 45117236fe29SJohannes Berg if (skb_queue_empty(&local->pending[i])) 45123a25a8c8SJohannes Berg ieee80211_propagate_queue_wake(local, i); 4513e2ebc74dSJohannes Berg } 45143b8d81e0SJohannes Berg spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 45152a577d98SJohannes Berg 4516f0e72851SJohannes Berg rcu_read_unlock(); 4517e2ebc74dSJohannes Berg } 4518e2ebc74dSJohannes Berg 4519e2ebc74dSJohannes Berg /* functions for drivers to get certain frames */ 4520e2ebc74dSJohannes Berg 4521eac70c13SMarco Porsch static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, 45226ec8c332SAndrei Otcheretianski struct ps_data *ps, struct sk_buff *skb, 45236ec8c332SAndrei Otcheretianski bool is_template) 4524e2ebc74dSJohannes Berg { 4525e2ebc74dSJohannes Berg u8 *pos, *tim; 4526e2ebc74dSJohannes Berg int aid0 = 0; 4527e2ebc74dSJohannes Berg int i, have_bits = 0, n1, n2; 4528e2ebc74dSJohannes Berg 4529e2ebc74dSJohannes Berg /* Generate bitmap for TIM only if there are any STAs in power save 4530e2ebc74dSJohannes Berg * mode. */ 4531d012a605SMarco Porsch if (atomic_read(&ps->num_sta_ps) > 0) 4532e2ebc74dSJohannes Berg /* in the hope that this is faster than 4533e2ebc74dSJohannes Berg * checking byte-for-byte */ 4534d012a605SMarco Porsch have_bits = !bitmap_empty((unsigned long *)ps->tim, 4535e2ebc74dSJohannes Berg IEEE80211_MAX_AID+1); 45366ec8c332SAndrei Otcheretianski if (!is_template) { 4537d012a605SMarco Porsch if (ps->dtim_count == 0) 4538d012a605SMarco Porsch ps->dtim_count = sdata->vif.bss_conf.dtim_period - 1; 4539e2ebc74dSJohannes Berg else 4540d012a605SMarco Porsch ps->dtim_count--; 45416ec8c332SAndrei Otcheretianski } 4542e2ebc74dSJohannes Berg 45434df864c1SJohannes Berg tim = pos = skb_put(skb, 6); 4544e2ebc74dSJohannes Berg *pos++ = WLAN_EID_TIM; 4545e2ebc74dSJohannes Berg *pos++ = 4; 4546d012a605SMarco Porsch *pos++ = ps->dtim_count; 45478860020eSJohannes Berg *pos++ = sdata->vif.bss_conf.dtim_period; 4548e2ebc74dSJohannes Berg 4549d012a605SMarco Porsch if (ps->dtim_count == 0 && !skb_queue_empty(&ps->bc_buf)) 4550e2ebc74dSJohannes Berg aid0 = 1; 4551e2ebc74dSJohannes Berg 4552d012a605SMarco Porsch ps->dtim_bc_mc = aid0 == 1; 4553512119b3SChristian Lamparter 4554e2ebc74dSJohannes Berg if (have_bits) { 4555e2ebc74dSJohannes Berg /* Find largest even number N1 so that bits numbered 1 through 4556e2ebc74dSJohannes Berg * (N1 x 8) - 1 in the bitmap are 0 and number N2 so that bits 4557e2ebc74dSJohannes Berg * (N2 + 1) x 8 through 2007 are 0. */ 4558e2ebc74dSJohannes Berg n1 = 0; 4559e2ebc74dSJohannes Berg for (i = 0; i < IEEE80211_MAX_TIM_LEN; i++) { 4560d012a605SMarco Porsch if (ps->tim[i]) { 4561e2ebc74dSJohannes Berg n1 = i & 0xfe; 4562e2ebc74dSJohannes Berg break; 4563e2ebc74dSJohannes Berg } 4564e2ebc74dSJohannes Berg } 4565e2ebc74dSJohannes Berg n2 = n1; 4566e2ebc74dSJohannes Berg for (i = IEEE80211_MAX_TIM_LEN - 1; i >= n1; i--) { 4567d012a605SMarco Porsch if (ps->tim[i]) { 4568e2ebc74dSJohannes Berg n2 = i; 4569e2ebc74dSJohannes Berg break; 4570e2ebc74dSJohannes Berg } 4571e2ebc74dSJohannes Berg } 4572e2ebc74dSJohannes Berg 4573e2ebc74dSJohannes Berg /* Bitmap control */ 4574e2ebc74dSJohannes Berg *pos++ = n1 | aid0; 4575e2ebc74dSJohannes Berg /* Part Virt Bitmap */ 45765220da39SEliad Peller skb_put(skb, n2 - n1); 4577d012a605SMarco Porsch memcpy(pos, ps->tim + n1, n2 - n1 + 1); 4578e2ebc74dSJohannes Berg 4579e2ebc74dSJohannes Berg tim[1] = n2 - n1 + 4; 4580e2ebc74dSJohannes Berg } else { 4581e2ebc74dSJohannes Berg *pos++ = aid0; /* Bitmap control */ 4582e2ebc74dSJohannes Berg *pos++ = 0; /* Part Virt Bitmap */ 4583e2ebc74dSJohannes Berg } 4584e2ebc74dSJohannes Berg } 4585e2ebc74dSJohannes Berg 4586eac70c13SMarco Porsch static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, 45876ec8c332SAndrei Otcheretianski struct ps_data *ps, struct sk_buff *skb, 45886ec8c332SAndrei Otcheretianski bool is_template) 4589eac70c13SMarco Porsch { 4590eac70c13SMarco Porsch struct ieee80211_local *local = sdata->local; 4591eac70c13SMarco Porsch 4592eac70c13SMarco Porsch /* 4593eac70c13SMarco Porsch * Not very nice, but we want to allow the driver to call 4594eac70c13SMarco Porsch * ieee80211_beacon_get() as a response to the set_tim() 4595eac70c13SMarco Porsch * callback. That, however, is already invoked under the 4596eac70c13SMarco Porsch * sta_lock to guarantee consistent and race-free update 4597eac70c13SMarco Porsch * of the tim bitmap in mac80211 and the driver. 4598eac70c13SMarco Porsch */ 4599eac70c13SMarco Porsch if (local->tim_in_locked_section) { 46006ec8c332SAndrei Otcheretianski __ieee80211_beacon_add_tim(sdata, ps, skb, is_template); 4601eac70c13SMarco Porsch } else { 46021b91731dSJohannes Berg spin_lock_bh(&local->tim_lock); 46036ec8c332SAndrei Otcheretianski __ieee80211_beacon_add_tim(sdata, ps, skb, is_template); 46041b91731dSJohannes Berg spin_unlock_bh(&local->tim_lock); 4605eac70c13SMarco Porsch } 4606eac70c13SMarco Porsch 4607eac70c13SMarco Porsch return 0; 4608eac70c13SMarco Porsch } 4609eac70c13SMarco Porsch 46108552a434SJohn Crispin static void ieee80211_set_beacon_cntdwn(struct ieee80211_sub_if_data *sdata, 461173da7d5bSSimon Wunderlich struct beacon_data *beacon) 461273da7d5bSSimon Wunderlich { 461373da7d5bSSimon Wunderlich struct probe_resp *resp; 4614cd7760e6SSimon Wunderlich u8 *beacon_data; 4615cd7760e6SSimon Wunderlich size_t beacon_data_len; 46160d06d9baSAndrei Otcheretianski int i; 46178552a434SJohn Crispin u8 count = beacon->cntdwn_current_counter; 461873da7d5bSSimon Wunderlich 4619cd7760e6SSimon Wunderlich switch (sdata->vif.type) { 4620cd7760e6SSimon Wunderlich case NL80211_IFTYPE_AP: 4621cd7760e6SSimon Wunderlich beacon_data = beacon->tail; 4622cd7760e6SSimon Wunderlich beacon_data_len = beacon->tail_len; 4623cd7760e6SSimon Wunderlich break; 4624cd7760e6SSimon Wunderlich case NL80211_IFTYPE_ADHOC: 4625cd7760e6SSimon Wunderlich beacon_data = beacon->head; 4626cd7760e6SSimon Wunderlich beacon_data_len = beacon->head_len; 4627cd7760e6SSimon Wunderlich break; 4628b8456a14SChun-Yeow Yeoh case NL80211_IFTYPE_MESH_POINT: 4629b8456a14SChun-Yeow Yeoh beacon_data = beacon->head; 4630b8456a14SChun-Yeow Yeoh beacon_data_len = beacon->head_len; 4631b8456a14SChun-Yeow Yeoh break; 4632cd7760e6SSimon Wunderlich default: 4633cd7760e6SSimon Wunderlich return; 4634cd7760e6SSimon Wunderlich } 46350d06d9baSAndrei Otcheretianski 463673da7d5bSSimon Wunderlich rcu_read_lock(); 46378552a434SJohn Crispin for (i = 0; i < IEEE80211_MAX_CNTDWN_COUNTERS_NUM; ++i) { 463873da7d5bSSimon Wunderlich resp = rcu_dereference(sdata->u.ap.probe_resp); 463973da7d5bSSimon Wunderlich 46408552a434SJohn Crispin if (beacon->cntdwn_counter_offsets[i]) { 46418552a434SJohn Crispin if (WARN_ON_ONCE(beacon->cntdwn_counter_offsets[i] >= 4642af296bdbSMichal Kazior beacon_data_len)) { 464373da7d5bSSimon Wunderlich rcu_read_unlock(); 464473da7d5bSSimon Wunderlich return; 464573da7d5bSSimon Wunderlich } 4646af296bdbSMichal Kazior 46478552a434SJohn Crispin beacon_data[beacon->cntdwn_counter_offsets[i]] = count; 4648af296bdbSMichal Kazior } 4649af296bdbSMichal Kazior 4650af296bdbSMichal Kazior if (sdata->vif.type == NL80211_IFTYPE_AP && resp) 46518552a434SJohn Crispin resp->data[resp->cntdwn_counter_offsets[i]] = count; 4652af296bdbSMichal Kazior } 465373da7d5bSSimon Wunderlich rcu_read_unlock(); 465473da7d5bSSimon Wunderlich } 46551af586c9SAndrei Otcheretianski 46568552a434SJohn Crispin static u8 __ieee80211_beacon_update_cntdwn(struct beacon_data *beacon) 4657e996ec2aSWojciech Dubowik { 46588552a434SJohn Crispin beacon->cntdwn_current_counter--; 4659e996ec2aSWojciech Dubowik 4660e996ec2aSWojciech Dubowik /* the counter should never reach 0 */ 46618552a434SJohn Crispin WARN_ON_ONCE(!beacon->cntdwn_current_counter); 4662e996ec2aSWojciech Dubowik 46638552a434SJohn Crispin return beacon->cntdwn_current_counter; 4664e996ec2aSWojciech Dubowik } 4665e996ec2aSWojciech Dubowik 46668552a434SJohn Crispin u8 ieee80211_beacon_update_cntdwn(struct ieee80211_vif *vif) 46671af586c9SAndrei Otcheretianski { 46681af586c9SAndrei Otcheretianski struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 4669af296bdbSMichal Kazior struct beacon_data *beacon = NULL; 4670af296bdbSMichal Kazior u8 count = 0; 467173da7d5bSSimon Wunderlich 4672af296bdbSMichal Kazior rcu_read_lock(); 4673af296bdbSMichal Kazior 4674af296bdbSMichal Kazior if (sdata->vif.type == NL80211_IFTYPE_AP) 4675af296bdbSMichal Kazior beacon = rcu_dereference(sdata->u.ap.beacon); 4676af296bdbSMichal Kazior else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) 4677af296bdbSMichal Kazior beacon = rcu_dereference(sdata->u.ibss.presp); 4678af296bdbSMichal Kazior else if (ieee80211_vif_is_mesh(&sdata->vif)) 4679af296bdbSMichal Kazior beacon = rcu_dereference(sdata->u.mesh.beacon); 4680af296bdbSMichal Kazior 4681af296bdbSMichal Kazior if (!beacon) 4682af296bdbSMichal Kazior goto unlock; 4683af296bdbSMichal Kazior 46848552a434SJohn Crispin count = __ieee80211_beacon_update_cntdwn(beacon); 46851af586c9SAndrei Otcheretianski 4686af296bdbSMichal Kazior unlock: 4687af296bdbSMichal Kazior rcu_read_unlock(); 4688af296bdbSMichal Kazior return count; 46890d06d9baSAndrei Otcheretianski } 46908552a434SJohn Crispin EXPORT_SYMBOL(ieee80211_beacon_update_cntdwn); 46910d06d9baSAndrei Otcheretianski 46928552a434SJohn Crispin void ieee80211_beacon_set_cntdwn(struct ieee80211_vif *vif, u8 counter) 469303737001SGregory Greenman { 469403737001SGregory Greenman struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 469503737001SGregory Greenman struct beacon_data *beacon = NULL; 469603737001SGregory Greenman 469703737001SGregory Greenman rcu_read_lock(); 469803737001SGregory Greenman 469903737001SGregory Greenman if (sdata->vif.type == NL80211_IFTYPE_AP) 470003737001SGregory Greenman beacon = rcu_dereference(sdata->u.ap.beacon); 470103737001SGregory Greenman else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) 470203737001SGregory Greenman beacon = rcu_dereference(sdata->u.ibss.presp); 470303737001SGregory Greenman else if (ieee80211_vif_is_mesh(&sdata->vif)) 470403737001SGregory Greenman beacon = rcu_dereference(sdata->u.mesh.beacon); 470503737001SGregory Greenman 470603737001SGregory Greenman if (!beacon) 470703737001SGregory Greenman goto unlock; 470803737001SGregory Greenman 47098552a434SJohn Crispin if (counter < beacon->cntdwn_current_counter) 47108552a434SJohn Crispin beacon->cntdwn_current_counter = counter; 471103737001SGregory Greenman 471203737001SGregory Greenman unlock: 471303737001SGregory Greenman rcu_read_unlock(); 471403737001SGregory Greenman } 47158552a434SJohn Crispin EXPORT_SYMBOL(ieee80211_beacon_set_cntdwn); 471603737001SGregory Greenman 47178552a434SJohn Crispin bool ieee80211_beacon_cntdwn_is_complete(struct ieee80211_vif *vif) 471873da7d5bSSimon Wunderlich { 471973da7d5bSSimon Wunderlich struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 472073da7d5bSSimon Wunderlich struct beacon_data *beacon = NULL; 472173da7d5bSSimon Wunderlich u8 *beacon_data; 472273da7d5bSSimon Wunderlich size_t beacon_data_len; 472373da7d5bSSimon Wunderlich int ret = false; 472473da7d5bSSimon Wunderlich 472573da7d5bSSimon Wunderlich if (!ieee80211_sdata_running(sdata)) 472673da7d5bSSimon Wunderlich return false; 472773da7d5bSSimon Wunderlich 472873da7d5bSSimon Wunderlich rcu_read_lock(); 472973da7d5bSSimon Wunderlich if (vif->type == NL80211_IFTYPE_AP) { 473073da7d5bSSimon Wunderlich struct ieee80211_if_ap *ap = &sdata->u.ap; 473173da7d5bSSimon Wunderlich 473273da7d5bSSimon Wunderlich beacon = rcu_dereference(ap->beacon); 473373da7d5bSSimon Wunderlich if (WARN_ON(!beacon || !beacon->tail)) 473473da7d5bSSimon Wunderlich goto out; 473573da7d5bSSimon Wunderlich beacon_data = beacon->tail; 473673da7d5bSSimon Wunderlich beacon_data_len = beacon->tail_len; 4737cd7760e6SSimon Wunderlich } else if (vif->type == NL80211_IFTYPE_ADHOC) { 4738cd7760e6SSimon Wunderlich struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 4739cd7760e6SSimon Wunderlich 4740cd7760e6SSimon Wunderlich beacon = rcu_dereference(ifibss->presp); 4741cd7760e6SSimon Wunderlich if (!beacon) 4742cd7760e6SSimon Wunderlich goto out; 4743cd7760e6SSimon Wunderlich 4744cd7760e6SSimon Wunderlich beacon_data = beacon->head; 4745cd7760e6SSimon Wunderlich beacon_data_len = beacon->head_len; 4746b8456a14SChun-Yeow Yeoh } else if (vif->type == NL80211_IFTYPE_MESH_POINT) { 4747b8456a14SChun-Yeow Yeoh struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 4748b8456a14SChun-Yeow Yeoh 4749b8456a14SChun-Yeow Yeoh beacon = rcu_dereference(ifmsh->beacon); 4750b8456a14SChun-Yeow Yeoh if (!beacon) 4751b8456a14SChun-Yeow Yeoh goto out; 4752b8456a14SChun-Yeow Yeoh 4753b8456a14SChun-Yeow Yeoh beacon_data = beacon->head; 4754b8456a14SChun-Yeow Yeoh beacon_data_len = beacon->head_len; 475573da7d5bSSimon Wunderlich } else { 475673da7d5bSSimon Wunderlich WARN_ON(1); 475773da7d5bSSimon Wunderlich goto out; 475873da7d5bSSimon Wunderlich } 475973da7d5bSSimon Wunderlich 47608552a434SJohn Crispin if (!beacon->cntdwn_counter_offsets[0]) 476110d78f27SMichal Kazior goto out; 476210d78f27SMichal Kazior 47638552a434SJohn Crispin if (WARN_ON_ONCE(beacon->cntdwn_counter_offsets[0] > beacon_data_len)) 476473da7d5bSSimon Wunderlich goto out; 476573da7d5bSSimon Wunderlich 47668552a434SJohn Crispin if (beacon_data[beacon->cntdwn_counter_offsets[0]] == 1) 476773da7d5bSSimon Wunderlich ret = true; 47688552a434SJohn Crispin 476973da7d5bSSimon Wunderlich out: 477073da7d5bSSimon Wunderlich rcu_read_unlock(); 477173da7d5bSSimon Wunderlich 477273da7d5bSSimon Wunderlich return ret; 477373da7d5bSSimon Wunderlich } 47748552a434SJohn Crispin EXPORT_SYMBOL(ieee80211_beacon_cntdwn_is_complete); 477573da7d5bSSimon Wunderlich 47760a3a8436SJouni Malinen static int ieee80211_beacon_protect(struct sk_buff *skb, 47770a3a8436SJouni Malinen struct ieee80211_local *local, 47780a3a8436SJouni Malinen struct ieee80211_sub_if_data *sdata) 47790a3a8436SJouni Malinen { 47800a3a8436SJouni Malinen ieee80211_tx_result res; 47810a3a8436SJouni Malinen struct ieee80211_tx_data tx; 478295247705SJohannes Berg struct sk_buff *check_skb; 47830a3a8436SJouni Malinen 47840a3a8436SJouni Malinen memset(&tx, 0, sizeof(tx)); 47850a3a8436SJouni Malinen tx.key = rcu_dereference(sdata->default_beacon_key); 47860a3a8436SJouni Malinen if (!tx.key) 47870a3a8436SJouni Malinen return 0; 47880a3a8436SJouni Malinen tx.local = local; 47890a3a8436SJouni Malinen tx.sdata = sdata; 47900a3a8436SJouni Malinen __skb_queue_head_init(&tx.skbs); 47910a3a8436SJouni Malinen __skb_queue_tail(&tx.skbs, skb); 47920a3a8436SJouni Malinen res = ieee80211_tx_h_encrypt(&tx); 479395247705SJohannes Berg check_skb = __skb_dequeue(&tx.skbs); 479495247705SJohannes Berg /* we may crash after this, but it'd be a bug in crypto */ 479595247705SJohannes Berg WARN_ON(check_skb != skb); 47960a3a8436SJouni Malinen if (WARN_ON_ONCE(res != TX_CONTINUE)) 479795247705SJohannes Berg return -EINVAL; 47980a3a8436SJouni Malinen 47990a3a8436SJouni Malinen return 0; 48000a3a8436SJouni Malinen } 48010a3a8436SJouni Malinen 48026ec8c332SAndrei Otcheretianski static struct sk_buff * 48036ec8c332SAndrei Otcheretianski __ieee80211_beacon_get(struct ieee80211_hw *hw, 4804eddcbb94SJohannes Berg struct ieee80211_vif *vif, 48056ec8c332SAndrei Otcheretianski struct ieee80211_mutable_offsets *offs, 48066ec8c332SAndrei Otcheretianski bool is_template) 4807e2ebc74dSJohannes Berg { 4808e2ebc74dSJohannes Berg struct ieee80211_local *local = hw_to_local(hw); 4809af296bdbSMichal Kazior struct beacon_data *beacon = NULL; 48109d139c81SJohannes Berg struct sk_buff *skb = NULL; 4811e039fa4aSJohannes Berg struct ieee80211_tx_info *info; 4812e2ebc74dSJohannes Berg struct ieee80211_sub_if_data *sdata = NULL; 481357fbcce3SJohannes Berg enum nl80211_band band; 4814e00cfce0SJouni Malinen struct ieee80211_tx_rate_control txrc; 481555de908aSJohannes Berg struct ieee80211_chanctx_conf *chanctx_conf; 48161af586c9SAndrei Otcheretianski int csa_off_base = 0; 48178318d78aSJohannes Berg 48185dfdaf58SJohannes Berg rcu_read_lock(); 4819e2ebc74dSJohannes Berg 482032bfd35dSJohannes Berg sdata = vif_to_sdata(vif); 482155de908aSJohannes Berg chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 482233b64eb2SLuis Carlos Cobo 482355de908aSJohannes Berg if (!ieee80211_sdata_running(sdata) || !chanctx_conf) 4824eb3e554bSFelix Fietkau goto out; 4825eb3e554bSFelix Fietkau 48266ec8c332SAndrei Otcheretianski if (offs) 48276ec8c332SAndrei Otcheretianski memset(offs, 0, sizeof(*offs)); 4828eddcbb94SJohannes Berg 482905c914feSJohannes Berg if (sdata->vif.type == NL80211_IFTYPE_AP) { 4830d012a605SMarco Porsch struct ieee80211_if_ap *ap = &sdata->u.ap; 4831d012a605SMarco Porsch 4832af296bdbSMichal Kazior beacon = rcu_dereference(ap->beacon); 48333ad97fbcSDan Carpenter if (beacon) { 48348552a434SJohn Crispin if (beacon->cntdwn_counter_offsets[0]) { 48351af586c9SAndrei Otcheretianski if (!is_template) 48368552a434SJohn Crispin ieee80211_beacon_update_cntdwn(vif); 48371af586c9SAndrei Otcheretianski 48388552a434SJohn Crispin ieee80211_set_beacon_cntdwn(sdata, beacon); 48391af586c9SAndrei Otcheretianski } 484073da7d5bSSimon Wunderlich 4841902acc78SJohannes Berg /* 4842902acc78SJohannes Berg * headroom, head length, 4843902acc78SJohannes Berg * tail length and maximum TIM length 4844902acc78SJohannes Berg */ 4845902acc78SJohannes Berg skb = dev_alloc_skb(local->tx_headroom + 4846902acc78SJohannes Berg beacon->head_len + 484770dabeb7SFelix Fietkau beacon->tail_len + 256 + 484870dabeb7SFelix Fietkau local->hw.extra_beacon_tailroom); 4849e2ebc74dSJohannes Berg if (!skb) 48505dfdaf58SJohannes Berg goto out; 4851e2ebc74dSJohannes Berg 4852e2ebc74dSJohannes Berg skb_reserve(skb, local->tx_headroom); 485359ae1d12SJohannes Berg skb_put_data(skb, beacon->head, beacon->head_len); 4854e2ebc74dSJohannes Berg 48556ec8c332SAndrei Otcheretianski ieee80211_beacon_add_tim(sdata, &ap->ps, skb, 48566ec8c332SAndrei Otcheretianski is_template); 4857e2ebc74dSJohannes Berg 48586ec8c332SAndrei Otcheretianski if (offs) { 48596ec8c332SAndrei Otcheretianski offs->tim_offset = beacon->head_len; 48606ec8c332SAndrei Otcheretianski offs->tim_length = skb->len - beacon->head_len; 48611af586c9SAndrei Otcheretianski 48621af586c9SAndrei Otcheretianski /* for AP the csa offsets are from tail */ 48631af586c9SAndrei Otcheretianski csa_off_base = skb->len; 48646ec8c332SAndrei Otcheretianski } 4865eddcbb94SJohannes Berg 48665dfdaf58SJohannes Berg if (beacon->tail) 486759ae1d12SJohannes Berg skb_put_data(skb, beacon->tail, 486859ae1d12SJohannes Berg beacon->tail_len); 48690a3a8436SJouni Malinen 48700a3a8436SJouni Malinen if (ieee80211_beacon_protect(skb, local, sdata) < 0) 48710a3a8436SJouni Malinen goto out; 48729d139c81SJohannes Berg } else 48739d139c81SJohannes Berg goto out; 487405c914feSJohannes Berg } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { 487546900298SJohannes Berg struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 48769d139c81SJohannes Berg struct ieee80211_hdr *hdr; 487733b64eb2SLuis Carlos Cobo 4878af296bdbSMichal Kazior beacon = rcu_dereference(ifibss->presp); 4879af296bdbSMichal Kazior if (!beacon) 48809d139c81SJohannes Berg goto out; 48819d139c81SJohannes Berg 48828552a434SJohn Crispin if (beacon->cntdwn_counter_offsets[0]) { 48831af586c9SAndrei Otcheretianski if (!is_template) 48848552a434SJohn Crispin __ieee80211_beacon_update_cntdwn(beacon); 4885cd7760e6SSimon Wunderlich 48868552a434SJohn Crispin ieee80211_set_beacon_cntdwn(sdata, beacon); 48871af586c9SAndrei Otcheretianski } 4888cd7760e6SSimon Wunderlich 4889af296bdbSMichal Kazior skb = dev_alloc_skb(local->tx_headroom + beacon->head_len + 489070dabeb7SFelix Fietkau local->hw.extra_beacon_tailroom); 48919d139c81SJohannes Berg if (!skb) 48929d139c81SJohannes Berg goto out; 4893c3ffeab4SJohannes Berg skb_reserve(skb, local->tx_headroom); 489459ae1d12SJohannes Berg skb_put_data(skb, beacon->head, beacon->head_len); 48959d139c81SJohannes Berg 48969d139c81SJohannes Berg hdr = (struct ieee80211_hdr *) skb->data; 4897e7827a70SHarvey Harrison hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 48989d139c81SJohannes Berg IEEE80211_STYPE_BEACON); 4899902acc78SJohannes Berg } else if (ieee80211_vif_is_mesh(&sdata->vif)) { 4900dbf498fbSJavier Cardona struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 4901472dbc45SJohannes Berg 4902af296bdbSMichal Kazior beacon = rcu_dereference(ifmsh->beacon); 4903af296bdbSMichal Kazior if (!beacon) 4904ac1bd846SJohannes Berg goto out; 4905ac1bd846SJohannes Berg 49068552a434SJohn Crispin if (beacon->cntdwn_counter_offsets[0]) { 49071af586c9SAndrei Otcheretianski if (!is_template) 49081af586c9SAndrei Otcheretianski /* TODO: For mesh csa_counter is in TU, so 49091af586c9SAndrei Otcheretianski * decrementing it by one isn't correct, but 49101af586c9SAndrei Otcheretianski * for now we leave it consistent with overall 49111af586c9SAndrei Otcheretianski * mac80211's behavior. 49121af586c9SAndrei Otcheretianski */ 49138552a434SJohn Crispin __ieee80211_beacon_update_cntdwn(beacon); 49141af586c9SAndrei Otcheretianski 49158552a434SJohn Crispin ieee80211_set_beacon_cntdwn(sdata, beacon); 49161af586c9SAndrei Otcheretianski } 4917b8456a14SChun-Yeow Yeoh 4918dbf498fbSJavier Cardona if (ifmsh->sync_ops) 4919445cd452SMasashi Honma ifmsh->sync_ops->adjust_tsf(sdata, beacon); 4920dbf498fbSJavier Cardona 49213b69a9c5SThomas Pedersen skb = dev_alloc_skb(local->tx_headroom + 4922af296bdbSMichal Kazior beacon->head_len + 49233f52b7e3SMarco Porsch 256 + /* TIM IE */ 4924af296bdbSMichal Kazior beacon->tail_len + 492570dabeb7SFelix Fietkau local->hw.extra_beacon_tailroom); 4926902acc78SJohannes Berg if (!skb) 4927902acc78SJohannes Berg goto out; 49282b5e1967SThomas Pedersen skb_reserve(skb, local->tx_headroom); 492959ae1d12SJohannes Berg skb_put_data(skb, beacon->head, beacon->head_len); 49306ec8c332SAndrei Otcheretianski ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb, is_template); 49316ec8c332SAndrei Otcheretianski 49326ec8c332SAndrei Otcheretianski if (offs) { 4933af296bdbSMichal Kazior offs->tim_offset = beacon->head_len; 4934af296bdbSMichal Kazior offs->tim_length = skb->len - beacon->head_len; 49356ec8c332SAndrei Otcheretianski } 49366ec8c332SAndrei Otcheretianski 493759ae1d12SJohannes Berg skb_put_data(skb, beacon->tail, beacon->tail_len); 49389d139c81SJohannes Berg } else { 49399d139c81SJohannes Berg WARN_ON(1); 494033b64eb2SLuis Carlos Cobo goto out; 494133b64eb2SLuis Carlos Cobo } 494233b64eb2SLuis Carlos Cobo 49431af586c9SAndrei Otcheretianski /* CSA offsets */ 4944af296bdbSMichal Kazior if (offs && beacon) { 49451af586c9SAndrei Otcheretianski int i; 49461af586c9SAndrei Otcheretianski 49478552a434SJohn Crispin for (i = 0; i < IEEE80211_MAX_CNTDWN_COUNTERS_NUM; i++) { 49488552a434SJohn Crispin u16 csa_off = beacon->cntdwn_counter_offsets[i]; 49491af586c9SAndrei Otcheretianski 49501af586c9SAndrei Otcheretianski if (!csa_off) 49511af586c9SAndrei Otcheretianski continue; 49521af586c9SAndrei Otcheretianski 49538552a434SJohn Crispin offs->cntdwn_counter_offs[i] = csa_off_base + csa_off; 49541af586c9SAndrei Otcheretianski } 49551af586c9SAndrei Otcheretianski } 49561af586c9SAndrei Otcheretianski 49574bf88530SJohannes Berg band = chanctx_conf->def.chan->band; 495855de908aSJohannes Berg 4959e039fa4aSJohannes Berg info = IEEE80211_SKB_CB(skb); 4960e039fa4aSJohannes Berg 49613b8d81e0SJohannes Berg info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; 4962e00cfce0SJouni Malinen info->flags |= IEEE80211_TX_CTL_NO_ACK; 4963e039fa4aSJohannes Berg info->band = band; 4964e00cfce0SJouni Malinen 4965e00cfce0SJouni Malinen memset(&txrc, 0, sizeof(txrc)); 4966e00cfce0SJouni Malinen txrc.hw = hw; 4967e31583cdSJohannes Berg txrc.sband = local->hw.wiphy->bands[band]; 4968e00cfce0SJouni Malinen txrc.bss_conf = &sdata->vif.bss_conf; 4969e00cfce0SJouni Malinen txrc.skb = skb; 4970e00cfce0SJouni Malinen txrc.reported_rate.idx = -1; 497108fad438SJouni Malinen if (sdata->beacon_rate_set && sdata->beacon_rateidx_mask[band]) 497208fad438SJouni Malinen txrc.rate_idx_mask = sdata->beacon_rateidx_mask[band]; 497308fad438SJouni Malinen else 497437eb0b16SJouni Malinen txrc.rate_idx_mask = sdata->rc_rateidx_mask[band]; 49758f0729b1SFelix Fietkau txrc.bss = true; 4976e00cfce0SJouni Malinen rate_control_get_rate(sdata, NULL, &txrc); 4977e2ebc74dSJohannes Berg 4978e039fa4aSJohannes Berg info->control.vif = vif; 4979f591fa5dSJohannes Berg 4980a472e71bSJohn W. Linville info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT | 4981a472e71bSJohn W. Linville IEEE80211_TX_CTL_ASSIGN_SEQ | 4982a472e71bSJohn W. Linville IEEE80211_TX_CTL_FIRST_FRAGMENT; 49835dfdaf58SJohannes Berg out: 49845dfdaf58SJohannes Berg rcu_read_unlock(); 4985e2ebc74dSJohannes Berg return skb; 49866ec8c332SAndrei Otcheretianski 49876ec8c332SAndrei Otcheretianski } 49886ec8c332SAndrei Otcheretianski 49896ec8c332SAndrei Otcheretianski struct sk_buff * 49906ec8c332SAndrei Otcheretianski ieee80211_beacon_get_template(struct ieee80211_hw *hw, 49916ec8c332SAndrei Otcheretianski struct ieee80211_vif *vif, 49926ec8c332SAndrei Otcheretianski struct ieee80211_mutable_offsets *offs) 49936ec8c332SAndrei Otcheretianski { 49946ec8c332SAndrei Otcheretianski return __ieee80211_beacon_get(hw, vif, offs, true); 49956ec8c332SAndrei Otcheretianski } 49966ec8c332SAndrei Otcheretianski EXPORT_SYMBOL(ieee80211_beacon_get_template); 49976ec8c332SAndrei Otcheretianski 49986ec8c332SAndrei Otcheretianski struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, 49996ec8c332SAndrei Otcheretianski struct ieee80211_vif *vif, 50006ec8c332SAndrei Otcheretianski u16 *tim_offset, u16 *tim_length) 50016ec8c332SAndrei Otcheretianski { 50026ec8c332SAndrei Otcheretianski struct ieee80211_mutable_offsets offs = {}; 50036ec8c332SAndrei Otcheretianski struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false); 500435afa588SHelmut Schaa struct sk_buff *copy; 500535afa588SHelmut Schaa struct ieee80211_supported_band *sband; 500635afa588SHelmut Schaa int shift; 500735afa588SHelmut Schaa 500835afa588SHelmut Schaa if (!bcn) 500935afa588SHelmut Schaa return bcn; 50106ec8c332SAndrei Otcheretianski 50116ec8c332SAndrei Otcheretianski if (tim_offset) 50126ec8c332SAndrei Otcheretianski *tim_offset = offs.tim_offset; 50136ec8c332SAndrei Otcheretianski 50146ec8c332SAndrei Otcheretianski if (tim_length) 50156ec8c332SAndrei Otcheretianski *tim_length = offs.tim_length; 50166ec8c332SAndrei Otcheretianski 501735afa588SHelmut Schaa if (ieee80211_hw_check(hw, BEACON_TX_STATUS) || 501835afa588SHelmut Schaa !hw_to_local(hw)->monitors) 501935afa588SHelmut Schaa return bcn; 502035afa588SHelmut Schaa 502135afa588SHelmut Schaa /* send a copy to monitor interfaces */ 502235afa588SHelmut Schaa copy = skb_copy(bcn, GFP_ATOMIC); 502335afa588SHelmut Schaa if (!copy) 502435afa588SHelmut Schaa return bcn; 502535afa588SHelmut Schaa 502635afa588SHelmut Schaa shift = ieee80211_vif_get_shift(vif); 502721a8e9ddSMohammed Shafi Shajakhan sband = ieee80211_get_sband(vif_to_sdata(vif)); 502821a8e9ddSMohammed Shafi Shajakhan if (!sband) 502921a8e9ddSMohammed Shafi Shajakhan return bcn; 503021a8e9ddSMohammed Shafi Shajakhan 5031b7b2e8caSJohn Crispin ieee80211_tx_monitor(hw_to_local(hw), copy, sband, 1, shift, false, 5032b7b2e8caSJohn Crispin NULL); 503335afa588SHelmut Schaa 50346ec8c332SAndrei Otcheretianski return bcn; 5035e2ebc74dSJohannes Berg } 5036eddcbb94SJohannes Berg EXPORT_SYMBOL(ieee80211_beacon_get_tim); 5037e2ebc74dSJohannes Berg 503802945821SArik Nemtsov struct sk_buff *ieee80211_proberesp_get(struct ieee80211_hw *hw, 503902945821SArik Nemtsov struct ieee80211_vif *vif) 504002945821SArik Nemtsov { 504102945821SArik Nemtsov struct ieee80211_if_ap *ap = NULL; 5042aa7a0080SEyal Shapira struct sk_buff *skb = NULL; 5043aa7a0080SEyal Shapira struct probe_resp *presp = NULL; 504402945821SArik Nemtsov struct ieee80211_hdr *hdr; 504502945821SArik Nemtsov struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 504602945821SArik Nemtsov 504702945821SArik Nemtsov if (sdata->vif.type != NL80211_IFTYPE_AP) 504802945821SArik Nemtsov return NULL; 504902945821SArik Nemtsov 505002945821SArik Nemtsov rcu_read_lock(); 505102945821SArik Nemtsov 505202945821SArik Nemtsov ap = &sdata->u.ap; 505302945821SArik Nemtsov presp = rcu_dereference(ap->probe_resp); 505402945821SArik Nemtsov if (!presp) 505502945821SArik Nemtsov goto out; 505602945821SArik Nemtsov 5057aa7a0080SEyal Shapira skb = dev_alloc_skb(presp->len); 505802945821SArik Nemtsov if (!skb) 505902945821SArik Nemtsov goto out; 506002945821SArik Nemtsov 506159ae1d12SJohannes Berg skb_put_data(skb, presp->data, presp->len); 5062aa7a0080SEyal Shapira 506302945821SArik Nemtsov hdr = (struct ieee80211_hdr *) skb->data; 506402945821SArik Nemtsov memset(hdr->addr1, 0, sizeof(hdr->addr1)); 506502945821SArik Nemtsov 506602945821SArik Nemtsov out: 506702945821SArik Nemtsov rcu_read_unlock(); 506802945821SArik Nemtsov return skb; 506902945821SArik Nemtsov } 507002945821SArik Nemtsov EXPORT_SYMBOL(ieee80211_proberesp_get); 507102945821SArik Nemtsov 5072295b02c4SAloka Dixit struct sk_buff *ieee80211_get_fils_discovery_tmpl(struct ieee80211_hw *hw, 5073295b02c4SAloka Dixit struct ieee80211_vif *vif) 5074295b02c4SAloka Dixit { 5075295b02c4SAloka Dixit struct sk_buff *skb = NULL; 5076295b02c4SAloka Dixit struct fils_discovery_data *tmpl = NULL; 5077295b02c4SAloka Dixit struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 5078295b02c4SAloka Dixit 5079295b02c4SAloka Dixit if (sdata->vif.type != NL80211_IFTYPE_AP) 5080295b02c4SAloka Dixit return NULL; 5081295b02c4SAloka Dixit 5082295b02c4SAloka Dixit rcu_read_lock(); 5083295b02c4SAloka Dixit tmpl = rcu_dereference(sdata->u.ap.fils_discovery); 5084295b02c4SAloka Dixit if (!tmpl) { 5085295b02c4SAloka Dixit rcu_read_unlock(); 5086295b02c4SAloka Dixit return NULL; 5087295b02c4SAloka Dixit } 5088295b02c4SAloka Dixit 5089295b02c4SAloka Dixit skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom + tmpl->len); 5090295b02c4SAloka Dixit if (skb) { 5091295b02c4SAloka Dixit skb_reserve(skb, sdata->local->hw.extra_tx_headroom); 5092295b02c4SAloka Dixit skb_put_data(skb, tmpl->data, tmpl->len); 5093295b02c4SAloka Dixit } 5094295b02c4SAloka Dixit 5095295b02c4SAloka Dixit rcu_read_unlock(); 5096295b02c4SAloka Dixit return skb; 5097295b02c4SAloka Dixit } 5098295b02c4SAloka Dixit EXPORT_SYMBOL(ieee80211_get_fils_discovery_tmpl); 5099295b02c4SAloka Dixit 5100632189a0SAloka Dixit struct sk_buff * 5101632189a0SAloka Dixit ieee80211_get_unsol_bcast_probe_resp_tmpl(struct ieee80211_hw *hw, 5102632189a0SAloka Dixit struct ieee80211_vif *vif) 5103632189a0SAloka Dixit { 5104632189a0SAloka Dixit struct sk_buff *skb = NULL; 5105632189a0SAloka Dixit struct unsol_bcast_probe_resp_data *tmpl = NULL; 5106632189a0SAloka Dixit struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 5107632189a0SAloka Dixit 5108632189a0SAloka Dixit if (sdata->vif.type != NL80211_IFTYPE_AP) 5109632189a0SAloka Dixit return NULL; 5110632189a0SAloka Dixit 5111632189a0SAloka Dixit rcu_read_lock(); 5112632189a0SAloka Dixit tmpl = rcu_dereference(sdata->u.ap.unsol_bcast_probe_resp); 5113632189a0SAloka Dixit if (!tmpl) { 5114632189a0SAloka Dixit rcu_read_unlock(); 5115632189a0SAloka Dixit return NULL; 5116632189a0SAloka Dixit } 5117632189a0SAloka Dixit 5118632189a0SAloka Dixit skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom + tmpl->len); 5119632189a0SAloka Dixit if (skb) { 5120632189a0SAloka Dixit skb_reserve(skb, sdata->local->hw.extra_tx_headroom); 5121632189a0SAloka Dixit skb_put_data(skb, tmpl->data, tmpl->len); 5122632189a0SAloka Dixit } 5123632189a0SAloka Dixit 5124632189a0SAloka Dixit rcu_read_unlock(); 5125632189a0SAloka Dixit return skb; 5126632189a0SAloka Dixit } 5127632189a0SAloka Dixit EXPORT_SYMBOL(ieee80211_get_unsol_bcast_probe_resp_tmpl); 5128632189a0SAloka Dixit 51297044cc56SKalle Valo struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw, 51307044cc56SKalle Valo struct ieee80211_vif *vif) 51317044cc56SKalle Valo { 51327044cc56SKalle Valo struct ieee80211_sub_if_data *sdata; 51337044cc56SKalle Valo struct ieee80211_if_managed *ifmgd; 51347044cc56SKalle Valo struct ieee80211_pspoll *pspoll; 51357044cc56SKalle Valo struct ieee80211_local *local; 51367044cc56SKalle Valo struct sk_buff *skb; 51377044cc56SKalle Valo 51387044cc56SKalle Valo if (WARN_ON(vif->type != NL80211_IFTYPE_STATION)) 51397044cc56SKalle Valo return NULL; 51407044cc56SKalle Valo 51417044cc56SKalle Valo sdata = vif_to_sdata(vif); 51427044cc56SKalle Valo ifmgd = &sdata->u.mgd; 51437044cc56SKalle Valo local = sdata->local; 51447044cc56SKalle Valo 51457044cc56SKalle Valo skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll)); 5146d15b8459SJoe Perches if (!skb) 51477044cc56SKalle Valo return NULL; 5148d15b8459SJoe Perches 51497044cc56SKalle Valo skb_reserve(skb, local->hw.extra_tx_headroom); 51507044cc56SKalle Valo 5151b080db58SJohannes Berg pspoll = skb_put_zero(skb, sizeof(*pspoll)); 51527044cc56SKalle Valo pspoll->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | 51537044cc56SKalle Valo IEEE80211_STYPE_PSPOLL); 51541db364c8SJohannes Berg pspoll->aid = cpu_to_le16(sdata->vif.bss_conf.aid); 51557044cc56SKalle Valo 51567044cc56SKalle Valo /* aid in PS-Poll has its two MSBs each set to 1 */ 51577044cc56SKalle Valo pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14); 51587044cc56SKalle Valo 51597044cc56SKalle Valo memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN); 51607044cc56SKalle Valo memcpy(pspoll->ta, vif->addr, ETH_ALEN); 51617044cc56SKalle Valo 51627044cc56SKalle Valo return skb; 51637044cc56SKalle Valo } 51647044cc56SKalle Valo EXPORT_SYMBOL(ieee80211_pspoll_get); 51657044cc56SKalle Valo 51667044cc56SKalle Valo struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, 51677b6ddeafSJohannes Berg struct ieee80211_vif *vif, 51687b6ddeafSJohannes Berg bool qos_ok) 51697044cc56SKalle Valo { 51707044cc56SKalle Valo struct ieee80211_hdr_3addr *nullfunc; 51717044cc56SKalle Valo struct ieee80211_sub_if_data *sdata; 51727044cc56SKalle Valo struct ieee80211_if_managed *ifmgd; 51737044cc56SKalle Valo struct ieee80211_local *local; 51747044cc56SKalle Valo struct sk_buff *skb; 51757b6ddeafSJohannes Berg bool qos = false; 51767044cc56SKalle Valo 51777044cc56SKalle Valo if (WARN_ON(vif->type != NL80211_IFTYPE_STATION)) 51787044cc56SKalle Valo return NULL; 51797044cc56SKalle Valo 51807044cc56SKalle Valo sdata = vif_to_sdata(vif); 51817044cc56SKalle Valo ifmgd = &sdata->u.mgd; 51827044cc56SKalle Valo local = sdata->local; 51837044cc56SKalle Valo 51847b6ddeafSJohannes Berg if (qos_ok) { 51857b6ddeafSJohannes Berg struct sta_info *sta; 51867b6ddeafSJohannes Berg 51877b6ddeafSJohannes Berg rcu_read_lock(); 51887b6ddeafSJohannes Berg sta = sta_info_get(sdata, ifmgd->bssid); 51897b6ddeafSJohannes Berg qos = sta && sta->sta.wme; 51907b6ddeafSJohannes Berg rcu_read_unlock(); 51917b6ddeafSJohannes Berg } 51927b6ddeafSJohannes Berg 51937b6ddeafSJohannes Berg skb = dev_alloc_skb(local->hw.extra_tx_headroom + 51947b6ddeafSJohannes Berg sizeof(*nullfunc) + 2); 5195d15b8459SJoe Perches if (!skb) 51967044cc56SKalle Valo return NULL; 5197d15b8459SJoe Perches 51987044cc56SKalle Valo skb_reserve(skb, local->hw.extra_tx_headroom); 51997044cc56SKalle Valo 5200b080db58SJohannes Berg nullfunc = skb_put_zero(skb, sizeof(*nullfunc)); 52017044cc56SKalle Valo nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | 52027044cc56SKalle Valo IEEE80211_STYPE_NULLFUNC | 52037044cc56SKalle Valo IEEE80211_FCTL_TODS); 52047b6ddeafSJohannes Berg if (qos) { 5205e0ba7095SJohannes Berg __le16 qoshdr = cpu_to_le16(7); 52067b6ddeafSJohannes Berg 52077b6ddeafSJohannes Berg BUILD_BUG_ON((IEEE80211_STYPE_QOS_NULLFUNC | 52087b6ddeafSJohannes Berg IEEE80211_STYPE_NULLFUNC) != 52097b6ddeafSJohannes Berg IEEE80211_STYPE_QOS_NULLFUNC); 52107b6ddeafSJohannes Berg nullfunc->frame_control |= 52117b6ddeafSJohannes Berg cpu_to_le16(IEEE80211_STYPE_QOS_NULLFUNC); 52127b6ddeafSJohannes Berg skb->priority = 7; 52137b6ddeafSJohannes Berg skb_set_queue_mapping(skb, IEEE80211_AC_VO); 5214e0ba7095SJohannes Berg skb_put_data(skb, &qoshdr, sizeof(qoshdr)); 52157b6ddeafSJohannes Berg } 52167b6ddeafSJohannes Berg 52177044cc56SKalle Valo memcpy(nullfunc->addr1, ifmgd->bssid, ETH_ALEN); 52187044cc56SKalle Valo memcpy(nullfunc->addr2, vif->addr, ETH_ALEN); 52197044cc56SKalle Valo memcpy(nullfunc->addr3, ifmgd->bssid, ETH_ALEN); 52207044cc56SKalle Valo 52217044cc56SKalle Valo return skb; 52227044cc56SKalle Valo } 52237044cc56SKalle Valo EXPORT_SYMBOL(ieee80211_nullfunc_get); 52247044cc56SKalle Valo 522505e54ea6SKalle Valo struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, 5226a344d677SJohannes Berg const u8 *src_addr, 522705e54ea6SKalle Valo const u8 *ssid, size_t ssid_len, 5228b9a9ada1SJohannes Berg size_t tailroom) 522905e54ea6SKalle Valo { 5230a344d677SJohannes Berg struct ieee80211_local *local = hw_to_local(hw); 523105e54ea6SKalle Valo struct ieee80211_hdr_3addr *hdr; 523205e54ea6SKalle Valo struct sk_buff *skb; 523305e54ea6SKalle Valo size_t ie_ssid_len; 523405e54ea6SKalle Valo u8 *pos; 523505e54ea6SKalle Valo 523605e54ea6SKalle Valo ie_ssid_len = 2 + ssid_len; 523705e54ea6SKalle Valo 523805e54ea6SKalle Valo skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*hdr) + 5239b9a9ada1SJohannes Berg ie_ssid_len + tailroom); 5240d15b8459SJoe Perches if (!skb) 524105e54ea6SKalle Valo return NULL; 524205e54ea6SKalle Valo 524305e54ea6SKalle Valo skb_reserve(skb, local->hw.extra_tx_headroom); 524405e54ea6SKalle Valo 5245b080db58SJohannes Berg hdr = skb_put_zero(skb, sizeof(*hdr)); 524605e54ea6SKalle Valo hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 524705e54ea6SKalle Valo IEEE80211_STYPE_PROBE_REQ); 5248e83e6541SJohannes Berg eth_broadcast_addr(hdr->addr1); 5249a344d677SJohannes Berg memcpy(hdr->addr2, src_addr, ETH_ALEN); 5250e83e6541SJohannes Berg eth_broadcast_addr(hdr->addr3); 525105e54ea6SKalle Valo 525205e54ea6SKalle Valo pos = skb_put(skb, ie_ssid_len); 525305e54ea6SKalle Valo *pos++ = WLAN_EID_SSID; 525405e54ea6SKalle Valo *pos++ = ssid_len; 525588c868c4SStanislaw Gruszka if (ssid_len) 525605e54ea6SKalle Valo memcpy(pos, ssid, ssid_len); 525705e54ea6SKalle Valo pos += ssid_len; 525805e54ea6SKalle Valo 525905e54ea6SKalle Valo return skb; 526005e54ea6SKalle Valo } 526105e54ea6SKalle Valo EXPORT_SYMBOL(ieee80211_probereq_get); 526205e54ea6SKalle Valo 526332bfd35dSJohannes Berg void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 5264e2ebc74dSJohannes Berg const void *frame, size_t frame_len, 5265e039fa4aSJohannes Berg const struct ieee80211_tx_info *frame_txctl, 5266e2ebc74dSJohannes Berg struct ieee80211_rts *rts) 5267e2ebc74dSJohannes Berg { 5268e2ebc74dSJohannes Berg const struct ieee80211_hdr *hdr = frame; 5269e2ebc74dSJohannes Berg 5270065e9605SHarvey Harrison rts->frame_control = 5271065e9605SHarvey Harrison cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS); 527232bfd35dSJohannes Berg rts->duration = ieee80211_rts_duration(hw, vif, frame_len, 527332bfd35dSJohannes Berg frame_txctl); 5274e2ebc74dSJohannes Berg memcpy(rts->ra, hdr->addr1, sizeof(rts->ra)); 5275e2ebc74dSJohannes Berg memcpy(rts->ta, hdr->addr2, sizeof(rts->ta)); 5276e2ebc74dSJohannes Berg } 5277e2ebc74dSJohannes Berg EXPORT_SYMBOL(ieee80211_rts_get); 5278e2ebc74dSJohannes Berg 527932bfd35dSJohannes Berg void ieee80211_ctstoself_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 5280e2ebc74dSJohannes Berg const void *frame, size_t frame_len, 5281e039fa4aSJohannes Berg const struct ieee80211_tx_info *frame_txctl, 5282e2ebc74dSJohannes Berg struct ieee80211_cts *cts) 5283e2ebc74dSJohannes Berg { 5284e2ebc74dSJohannes Berg const struct ieee80211_hdr *hdr = frame; 5285e2ebc74dSJohannes Berg 5286065e9605SHarvey Harrison cts->frame_control = 5287065e9605SHarvey Harrison cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); 528832bfd35dSJohannes Berg cts->duration = ieee80211_ctstoself_duration(hw, vif, 528932bfd35dSJohannes Berg frame_len, frame_txctl); 5290e2ebc74dSJohannes Berg memcpy(cts->ra, hdr->addr1, sizeof(cts->ra)); 5291e2ebc74dSJohannes Berg } 5292e2ebc74dSJohannes Berg EXPORT_SYMBOL(ieee80211_ctstoself_get); 5293e2ebc74dSJohannes Berg 5294e2ebc74dSJohannes Berg struct sk_buff * 529532bfd35dSJohannes Berg ieee80211_get_buffered_bc(struct ieee80211_hw *hw, 5296e039fa4aSJohannes Berg struct ieee80211_vif *vif) 5297e2ebc74dSJohannes Berg { 5298e2ebc74dSJohannes Berg struct ieee80211_local *local = hw_to_local(hw); 5299747cf5e9STomas Winkler struct sk_buff *skb = NULL; 53005cf121c3SJohannes Berg struct ieee80211_tx_data tx; 5301e2ebc74dSJohannes Berg struct ieee80211_sub_if_data *sdata; 5302d012a605SMarco Porsch struct ps_data *ps; 5303e039fa4aSJohannes Berg struct ieee80211_tx_info *info; 530455de908aSJohannes Berg struct ieee80211_chanctx_conf *chanctx_conf; 5305e2ebc74dSJohannes Berg 530632bfd35dSJohannes Berg sdata = vif_to_sdata(vif); 53075dfdaf58SJohannes Berg 53085dfdaf58SJohannes Berg rcu_read_lock(); 530955de908aSJohannes Berg chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 53105dfdaf58SJohannes Berg 5311d012a605SMarco Porsch if (!chanctx_conf) 5312747cf5e9STomas Winkler goto out; 53135dfdaf58SJohannes Berg 5314d012a605SMarco Porsch if (sdata->vif.type == NL80211_IFTYPE_AP) { 5315d012a605SMarco Porsch struct beacon_data *beacon = 5316d012a605SMarco Porsch rcu_dereference(sdata->u.ap.beacon); 5317d012a605SMarco Porsch 5318d012a605SMarco Porsch if (!beacon || !beacon->head) 5319d012a605SMarco Porsch goto out; 5320d012a605SMarco Porsch 5321d012a605SMarco Porsch ps = &sdata->u.ap.ps; 53223f52b7e3SMarco Porsch } else if (ieee80211_vif_is_mesh(&sdata->vif)) { 53233f52b7e3SMarco Porsch ps = &sdata->u.mesh.ps; 5324d012a605SMarco Porsch } else { 5325d012a605SMarco Porsch goto out; 5326d012a605SMarco Porsch } 5327d012a605SMarco Porsch 5328d012a605SMarco Porsch if (ps->dtim_count != 0 || !ps->dtim_bc_mc) 5329747cf5e9STomas Winkler goto out; /* send buffered bc/mc only after DTIM beacon */ 5330e039fa4aSJohannes Berg 5331e2ebc74dSJohannes Berg while (1) { 5332d012a605SMarco Porsch skb = skb_dequeue(&ps->bc_buf); 5333e2ebc74dSJohannes Berg if (!skb) 5334747cf5e9STomas Winkler goto out; 5335e2ebc74dSJohannes Berg local->total_ps_buffered--; 5336e2ebc74dSJohannes Berg 5337d012a605SMarco Porsch if (!skb_queue_empty(&ps->bc_buf) && skb->len >= 2) { 5338e2ebc74dSJohannes Berg struct ieee80211_hdr *hdr = 5339e2ebc74dSJohannes Berg (struct ieee80211_hdr *) skb->data; 5340e2ebc74dSJohannes Berg /* more buffered multicast/broadcast frames ==> set 5341e2ebc74dSJohannes Berg * MoreData flag in IEEE 802.11 header to inform PS 5342e2ebc74dSJohannes Berg * STAs */ 5343e2ebc74dSJohannes Berg hdr->frame_control |= 5344e2ebc74dSJohannes Berg cpu_to_le16(IEEE80211_FCTL_MOREDATA); 5345e2ebc74dSJohannes Berg } 5346e2ebc74dSJohannes Berg 5347112c44b2SMichael Braun if (sdata->vif.type == NL80211_IFTYPE_AP) 5348de74a1d9SMichael Braun sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev); 53497c10770fSJohannes Berg if (!ieee80211_tx_prepare(sdata, &tx, NULL, skb)) 5350e2ebc74dSJohannes Berg break; 53516b07d9caSFelix Fietkau ieee80211_free_txskb(hw, skb); 5352e2ebc74dSJohannes Berg } 5353e039fa4aSJohannes Berg 5354e039fa4aSJohannes Berg info = IEEE80211_SKB_CB(skb); 5355e039fa4aSJohannes Berg 53565cf121c3SJohannes Berg tx.flags |= IEEE80211_TX_PS_BUFFERED; 53574bf88530SJohannes Berg info->band = chanctx_conf->def.chan->band; 5358e2ebc74dSJohannes Berg 535997b045d6SJohannes Berg if (invoke_tx_handlers(&tx)) 5360e2ebc74dSJohannes Berg skb = NULL; 5361747cf5e9STomas Winkler out: 5362d0709a65SJohannes Berg rcu_read_unlock(); 5363e2ebc74dSJohannes Berg 5364e2ebc74dSJohannes Berg return skb; 5365e2ebc74dSJohannes Berg } 5366e2ebc74dSJohannes Berg EXPORT_SYMBOL(ieee80211_get_buffered_bc); 53673b8d81e0SJohannes Berg 5368b6da911bSLiad Kaufman int ieee80211_reserve_tid(struct ieee80211_sta *pubsta, u8 tid) 5369b6da911bSLiad Kaufman { 5370b6da911bSLiad Kaufman struct sta_info *sta = container_of(pubsta, struct sta_info, sta); 5371b6da911bSLiad Kaufman struct ieee80211_sub_if_data *sdata = sta->sdata; 5372b6da911bSLiad Kaufman struct ieee80211_local *local = sdata->local; 5373b6da911bSLiad Kaufman int ret; 5374b6da911bSLiad Kaufman u32 queues; 5375b6da911bSLiad Kaufman 5376b6da911bSLiad Kaufman lockdep_assert_held(&local->sta_mtx); 5377b6da911bSLiad Kaufman 5378b6da911bSLiad Kaufman /* only some cases are supported right now */ 5379b6da911bSLiad Kaufman switch (sdata->vif.type) { 5380b6da911bSLiad Kaufman case NL80211_IFTYPE_STATION: 5381b6da911bSLiad Kaufman case NL80211_IFTYPE_AP: 5382b6da911bSLiad Kaufman case NL80211_IFTYPE_AP_VLAN: 5383b6da911bSLiad Kaufman break; 5384b6da911bSLiad Kaufman default: 5385b6da911bSLiad Kaufman WARN_ON(1); 5386b6da911bSLiad Kaufman return -EINVAL; 5387b6da911bSLiad Kaufman } 5388b6da911bSLiad Kaufman 5389b6da911bSLiad Kaufman if (WARN_ON(tid >= IEEE80211_NUM_UPS)) 5390b6da911bSLiad Kaufman return -EINVAL; 5391b6da911bSLiad Kaufman 5392b6da911bSLiad Kaufman if (sta->reserved_tid == tid) { 5393b6da911bSLiad Kaufman ret = 0; 5394b6da911bSLiad Kaufman goto out; 5395b6da911bSLiad Kaufman } 5396b6da911bSLiad Kaufman 5397b6da911bSLiad Kaufman if (sta->reserved_tid != IEEE80211_TID_UNRESERVED) { 5398b6da911bSLiad Kaufman sdata_err(sdata, "TID reservation already active\n"); 5399b6da911bSLiad Kaufman ret = -EALREADY; 5400b6da911bSLiad Kaufman goto out; 5401b6da911bSLiad Kaufman } 5402b6da911bSLiad Kaufman 5403b6da911bSLiad Kaufman ieee80211_stop_vif_queues(sdata->local, sdata, 5404b6da911bSLiad Kaufman IEEE80211_QUEUE_STOP_REASON_RESERVE_TID); 5405b6da911bSLiad Kaufman 5406b6da911bSLiad Kaufman synchronize_net(); 5407b6da911bSLiad Kaufman 5408b6da911bSLiad Kaufman /* Tear down BA sessions so we stop aggregating on this TID */ 540930686bf7SJohannes Berg if (ieee80211_hw_check(&local->hw, AMPDU_AGGREGATION)) { 5410b6da911bSLiad Kaufman set_sta_flag(sta, WLAN_STA_BLOCK_BA); 5411b6da911bSLiad Kaufman __ieee80211_stop_tx_ba_session(sta, tid, 5412b6da911bSLiad Kaufman AGG_STOP_LOCAL_REQUEST); 5413b6da911bSLiad Kaufman } 5414b6da911bSLiad Kaufman 5415b6da911bSLiad Kaufman queues = BIT(sdata->vif.hw_queue[ieee802_1d_to_ac[tid]]); 54163b24f4c6SEmmanuel Grumbach __ieee80211_flush_queues(local, sdata, queues, false); 5417b6da911bSLiad Kaufman 5418b6da911bSLiad Kaufman sta->reserved_tid = tid; 5419b6da911bSLiad Kaufman 5420b6da911bSLiad Kaufman ieee80211_wake_vif_queues(local, sdata, 5421b6da911bSLiad Kaufman IEEE80211_QUEUE_STOP_REASON_RESERVE_TID); 5422b6da911bSLiad Kaufman 542330686bf7SJohannes Berg if (ieee80211_hw_check(&local->hw, AMPDU_AGGREGATION)) 5424b6da911bSLiad Kaufman clear_sta_flag(sta, WLAN_STA_BLOCK_BA); 5425b6da911bSLiad Kaufman 5426b6da911bSLiad Kaufman ret = 0; 5427b6da911bSLiad Kaufman out: 5428b6da911bSLiad Kaufman return ret; 5429b6da911bSLiad Kaufman } 5430b6da911bSLiad Kaufman EXPORT_SYMBOL(ieee80211_reserve_tid); 5431b6da911bSLiad Kaufman 5432b6da911bSLiad Kaufman void ieee80211_unreserve_tid(struct ieee80211_sta *pubsta, u8 tid) 5433b6da911bSLiad Kaufman { 5434b6da911bSLiad Kaufman struct sta_info *sta = container_of(pubsta, struct sta_info, sta); 5435b6da911bSLiad Kaufman struct ieee80211_sub_if_data *sdata = sta->sdata; 5436b6da911bSLiad Kaufman 5437b6da911bSLiad Kaufman lockdep_assert_held(&sdata->local->sta_mtx); 5438b6da911bSLiad Kaufman 5439b6da911bSLiad Kaufman /* only some cases are supported right now */ 5440b6da911bSLiad Kaufman switch (sdata->vif.type) { 5441b6da911bSLiad Kaufman case NL80211_IFTYPE_STATION: 5442b6da911bSLiad Kaufman case NL80211_IFTYPE_AP: 5443b6da911bSLiad Kaufman case NL80211_IFTYPE_AP_VLAN: 5444b6da911bSLiad Kaufman break; 5445b6da911bSLiad Kaufman default: 5446b6da911bSLiad Kaufman WARN_ON(1); 5447b6da911bSLiad Kaufman return; 5448b6da911bSLiad Kaufman } 5449b6da911bSLiad Kaufman 5450b6da911bSLiad Kaufman if (tid != sta->reserved_tid) { 5451b6da911bSLiad Kaufman sdata_err(sdata, "TID to unreserve (%d) isn't reserved\n", tid); 5452b6da911bSLiad Kaufman return; 5453b6da911bSLiad Kaufman } 5454b6da911bSLiad Kaufman 5455b6da911bSLiad Kaufman sta->reserved_tid = IEEE80211_TID_UNRESERVED; 5456b6da911bSLiad Kaufman } 5457b6da911bSLiad Kaufman EXPORT_SYMBOL(ieee80211_unreserve_tid); 5458b6da911bSLiad Kaufman 545955de908aSJohannes Berg void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, 546055de908aSJohannes Berg struct sk_buff *skb, int tid, 546108aca29aSMathy Vanhoef enum nl80211_band band) 54623b8d81e0SJohannes Berg { 5463731977e9SAmadeusz Sławiński int ac = ieee80211_ac_from_tid(tid); 54643a25a8c8SJohannes Berg 5465d57a544dSZhang Shengju skb_reset_mac_header(skb); 54663a25a8c8SJohannes Berg skb_set_queue_mapping(skb, ac); 5467cf6bb79aSHelmut Schaa skb->priority = tid; 5468cf0277e7SJohannes Berg 546989afe614SJohannes Berg skb->dev = sdata->dev; 547089afe614SJohannes Berg 54713d34deb6SJohannes Berg /* 54723d34deb6SJohannes Berg * The other path calling ieee80211_xmit is from the tasklet, 54733d34deb6SJohannes Berg * and while we can handle concurrent transmissions locking 54743d34deb6SJohannes Berg * requirements are that we do not come into tx with bhs on. 54753d34deb6SJohannes Berg */ 54763d34deb6SJohannes Berg local_bh_disable(); 547773c4e195SJohannes Berg IEEE80211_SKB_CB(skb)->band = band; 547808aca29aSMathy Vanhoef ieee80211_xmit(sdata, NULL, skb); 54793d34deb6SJohannes Berg local_bh_enable(); 54803b8d81e0SJohannes Berg } 548191180649SDenis Kenzior 548291180649SDenis Kenzior int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev, 548391180649SDenis Kenzior const u8 *buf, size_t len, 5484dca9ca2dSMarkus Theil const u8 *dest, __be16 proto, bool unencrypted, 5485dca9ca2dSMarkus Theil u64 *cookie) 548691180649SDenis Kenzior { 548791180649SDenis Kenzior struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 548891180649SDenis Kenzior struct ieee80211_local *local = sdata->local; 548910cb8e61SMarkus Theil struct sta_info *sta; 549091180649SDenis Kenzior struct sk_buff *skb; 549191180649SDenis Kenzior struct ethhdr *ehdr; 5492b95d2ccdSJohannes Berg u32 ctrl_flags = 0; 5493a7528198SMarkus Theil u32 flags = 0; 549491180649SDenis Kenzior 549591180649SDenis Kenzior /* Only accept CONTROL_PORT_PROTOCOL configured in CONNECT/ASSOCIATE 549691180649SDenis Kenzior * or Pre-Authentication 549791180649SDenis Kenzior */ 549891180649SDenis Kenzior if (proto != sdata->control_port_protocol && 549991180649SDenis Kenzior proto != cpu_to_be16(ETH_P_PREAUTH)) 550091180649SDenis Kenzior return -EINVAL; 550191180649SDenis Kenzior 5502b95d2ccdSJohannes Berg if (proto == sdata->control_port_protocol) 55035af7fef3SMarkus Theil ctrl_flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO | 55045af7fef3SMarkus Theil IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP; 5505b95d2ccdSJohannes Berg 550691180649SDenis Kenzior if (unencrypted) 5507a7528198SMarkus Theil flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; 5508a7528198SMarkus Theil 5509a7528198SMarkus Theil if (cookie) 5510a7528198SMarkus Theil ctrl_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; 5511a7528198SMarkus Theil 551210cb8e61SMarkus Theil flags |= IEEE80211_TX_INTFL_NL80211_FRAME_TX; 551391180649SDenis Kenzior 551491180649SDenis Kenzior skb = dev_alloc_skb(local->hw.extra_tx_headroom + 551591180649SDenis Kenzior sizeof(struct ethhdr) + len); 551691180649SDenis Kenzior if (!skb) 551791180649SDenis Kenzior return -ENOMEM; 551891180649SDenis Kenzior 551991180649SDenis Kenzior skb_reserve(skb, local->hw.extra_tx_headroom + sizeof(struct ethhdr)); 552091180649SDenis Kenzior 552191180649SDenis Kenzior skb_put_data(skb, buf, len); 552291180649SDenis Kenzior 552391180649SDenis Kenzior ehdr = skb_push(skb, sizeof(struct ethhdr)); 552491180649SDenis Kenzior memcpy(ehdr->h_dest, dest, ETH_ALEN); 55258079e4feSJohannes Berg memcpy(ehdr->h_source, sdata->vif.addr, ETH_ALEN); 552691180649SDenis Kenzior ehdr->h_proto = proto; 552791180649SDenis Kenzior 552891180649SDenis Kenzior skb->dev = dev; 552910cb8e61SMarkus Theil skb->protocol = proto; 553091180649SDenis Kenzior skb_reset_network_header(skb); 553191180649SDenis Kenzior skb_reset_mac_header(skb); 553291180649SDenis Kenzior 553310cb8e61SMarkus Theil /* update QoS header to prioritize control port frames if possible, 553410cb8e61SMarkus Theil * priorization also happens for control port frames send over 553510cb8e61SMarkus Theil * AF_PACKET 553610cb8e61SMarkus Theil */ 553710cb8e61SMarkus Theil rcu_read_lock(); 553810cb8e61SMarkus Theil 553910cb8e61SMarkus Theil if (ieee80211_lookup_ra_sta(sdata, skb, &sta) == 0 && !IS_ERR(sta)) { 554010cb8e61SMarkus Theil u16 queue = __ieee80211_select_queue(sdata, sta, skb); 554110cb8e61SMarkus Theil 554210cb8e61SMarkus Theil skb_set_queue_mapping(skb, queue); 554310cb8e61SMarkus Theil skb_get_hash(skb); 554410cb8e61SMarkus Theil } 554510cb8e61SMarkus Theil 554610cb8e61SMarkus Theil rcu_read_unlock(); 554710cb8e61SMarkus Theil 5548a7528198SMarkus Theil /* mutex lock is only needed for incrementing the cookie counter */ 5549a7528198SMarkus Theil mutex_lock(&local->mtx); 5550a7528198SMarkus Theil 5551e7441c92SDenis Kenzior local_bh_disable(); 5552a7528198SMarkus Theil __ieee80211_subif_start_xmit(skb, skb->dev, flags, ctrl_flags, cookie); 5553e7441c92SDenis Kenzior local_bh_enable(); 555491180649SDenis Kenzior 5555a7528198SMarkus Theil mutex_unlock(&local->mtx); 5556a7528198SMarkus Theil 555791180649SDenis Kenzior return 0; 555891180649SDenis Kenzior } 55598828f81aSRajkumar Manoharan 55608828f81aSRajkumar Manoharan int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev, 55618828f81aSRajkumar Manoharan const u8 *buf, size_t len) 55628828f81aSRajkumar Manoharan { 55638828f81aSRajkumar Manoharan struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 55648828f81aSRajkumar Manoharan struct ieee80211_local *local = sdata->local; 55658828f81aSRajkumar Manoharan struct sk_buff *skb; 55668828f81aSRajkumar Manoharan 55678828f81aSRajkumar Manoharan skb = dev_alloc_skb(local->hw.extra_tx_headroom + len + 55688828f81aSRajkumar Manoharan 30 + /* header size */ 55698828f81aSRajkumar Manoharan 18); /* 11s header size */ 55708828f81aSRajkumar Manoharan if (!skb) 55718828f81aSRajkumar Manoharan return -ENOMEM; 55728828f81aSRajkumar Manoharan 55738828f81aSRajkumar Manoharan skb_reserve(skb, local->hw.extra_tx_headroom); 55748828f81aSRajkumar Manoharan skb_put_data(skb, buf, len); 55758828f81aSRajkumar Manoharan 55768828f81aSRajkumar Manoharan skb->dev = dev; 55778828f81aSRajkumar Manoharan skb->protocol = htons(ETH_P_802_3); 55788828f81aSRajkumar Manoharan skb_reset_network_header(skb); 55798828f81aSRajkumar Manoharan skb_reset_mac_header(skb); 55808828f81aSRajkumar Manoharan 55818828f81aSRajkumar Manoharan local_bh_disable(); 55828828f81aSRajkumar Manoharan __ieee80211_subif_start_xmit(skb, skb->dev, 0, 5583a7528198SMarkus Theil IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP, 5584a7528198SMarkus Theil NULL); 5585e2ebc74dSJohannes Berg local_bh_enable(); 5586e2ebc74dSJohannes Berg 5587e2ebc74dSJohannes Berg return 0; 5588e2ebc74dSJohannes Berg } 5589