From 1dd536f1fa63d6ace1a4b3c558b64c84edfc726f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 23 Mar 2019 09:59:35 +0100 Subject: [PATCH] mac80211: improve performance by deferring tx queue selection Signed-off-by: Felix Fietkau --- ...ing-iTXQ-select-the-queue-in-ieee802.patch | 183 ++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 package/kernel/mac80211/patches/subsys/360-mac80211-when-using-iTXQ-select-the-queue-in-ieee802.patch diff --git a/package/kernel/mac80211/patches/subsys/360-mac80211-when-using-iTXQ-select-the-queue-in-ieee802.patch b/package/kernel/mac80211/patches/subsys/360-mac80211-when-using-iTXQ-select-the-queue-in-ieee802.patch new file mode 100644 index 0000000000..03d115071e --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/360-mac80211-when-using-iTXQ-select-the-queue-in-ieee802.patch @@ -0,0 +1,183 @@ +From: Felix Fietkau +Date: Fri, 22 Mar 2019 18:06:03 +0100 +Subject: [PATCH] mac80211: when using iTXQ, select the queue in + ieee80211_subif_start_xmit + +When using iTXQ, the network stack does not need the real queue number, since +mac80211 is using its internal queues anyway. In that case we can defer +selecting the queue and remove a redundant station lookup in the tx path to save +some CPU cycles. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -3753,6 +3753,7 @@ void __ieee80211_subif_start_xmit(struct + u32 info_flags) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ struct ieee80211_local *local = sdata->local; + struct sta_info *sta; + struct sk_buff *next; + +@@ -3766,7 +3767,15 @@ void __ieee80211_subif_start_xmit(struct + if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) + goto out_free; + +- if (!IS_ERR_OR_NULL(sta)) { ++ if (IS_ERR(sta)) ++ sta = NULL; ++ ++ if (local->ops->wake_tx_queue) { ++ u16 queue = __ieee80211_select_queue(sdata, sta, skb); ++ skb_set_queue_mapping(skb, queue); ++ } ++ ++ if (sta) { + struct ieee80211_fast_tx *fast_tx; + + /* We need a bit of data queued to build aggregates properly, so +--- a/net/mac80211/wme.c ++++ b/net/mac80211/wme.c +@@ -141,6 +141,42 @@ u16 ieee80211_select_queue_80211(struct + return ieee80211_downgrade_queue(sdata, NULL, skb); + } + ++u16 __ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, ++ struct sta_info *sta, struct sk_buff *skb) ++{ ++ struct mac80211_qos_map *qos_map; ++ bool qos; ++ ++ /* all mesh/ocb stations are required to support WME */ ++ if (sdata->vif.type == NL80211_IFTYPE_MESH_POINT || ++ sdata->vif.type == NL80211_IFTYPE_OCB) ++ qos = true; ++ else if (sta) ++ qos = sta->sta.wme; ++ else ++ qos = false; ++ ++ if (!qos) { ++ skb->priority = 0; /* required for correct WPA/11i MIC */ ++ return IEEE80211_AC_BE; ++ } ++ ++ if (skb->protocol == sdata->control_port_protocol) { ++ skb->priority = 7; ++ goto downgrade; ++ } ++ ++ /* use the data classifier to determine what 802.1d tag the ++ * data frame has */ ++ qos_map = rcu_dereference(sdata->qos_map); ++ skb->priority = cfg80211_classify8021d(skb, qos_map ? ++ &qos_map->qos_map : NULL); ++ ++ downgrade: ++ return ieee80211_downgrade_queue(sdata, sta, skb); ++} ++ ++ + /* Indicate which queue to use. */ + u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb) +@@ -148,10 +184,12 @@ u16 ieee80211_select_queue(struct ieee80 + struct ieee80211_local *local = sdata->local; + struct sta_info *sta = NULL; + const u8 *ra = NULL; +- bool qos = false; +- struct mac80211_qos_map *qos_map; + u16 ret; + ++ /* when using iTXQ, we can do this later */ ++ if (local->ops->wake_tx_queue) ++ return 0; ++ + if (local->hw.queues < IEEE80211_NUM_ACS || skb->len < 6) { + skb->priority = 0; /* required for correct WPA/11i MIC */ + return 0; +@@ -161,10 +199,8 @@ u16 ieee80211_select_queue(struct ieee80 + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP_VLAN: + sta = rcu_dereference(sdata->u.vlan.sta); +- if (sta) { +- qos = sta->sta.wme; ++ if (sta) + break; +- } + /* fall through */ + case NL80211_IFTYPE_AP: + ra = skb->data; +@@ -172,56 +208,26 @@ u16 ieee80211_select_queue(struct ieee80 + case NL80211_IFTYPE_WDS: + ra = sdata->u.wds.remote_addr; + break; +-#ifdef CPTCFG_MAC80211_MESH +- case NL80211_IFTYPE_MESH_POINT: +- qos = true; +- break; +-#endif + case NL80211_IFTYPE_STATION: + /* might be a TDLS station */ + sta = sta_info_get(sdata, skb->data); + if (sta) +- qos = sta->sta.wme; ++ break; + + ra = sdata->u.mgd.bssid; + break; + case NL80211_IFTYPE_ADHOC: + ra = skb->data; + break; +- case NL80211_IFTYPE_OCB: +- /* all stations are required to support WME */ +- qos = true; +- break; + default: + break; + } + +- if (!sta && ra && !is_multicast_ether_addr(ra)) { ++ if (!sta && ra && !is_multicast_ether_addr(ra)) + sta = sta_info_get(sdata, ra); +- if (sta) +- qos = sta->sta.wme; +- } + +- if (!qos) { +- skb->priority = 0; /* required for correct WPA/11i MIC */ +- ret = IEEE80211_AC_BE; +- goto out; +- } +- +- if (skb->protocol == sdata->control_port_protocol) { +- skb->priority = 7; +- goto downgrade; +- } +- +- /* use the data classifier to determine what 802.1d tag the +- * data frame has */ +- qos_map = rcu_dereference(sdata->qos_map); +- skb->priority = cfg80211_classify8021d(skb, qos_map ? +- &qos_map->qos_map : NULL); ++ ret = __ieee80211_select_queue(sdata, sta, skb); + +- downgrade: +- ret = ieee80211_downgrade_queue(sdata, sta, skb); +- out: + rcu_read_unlock(); + return ret; + } +--- a/net/mac80211/wme.h ++++ b/net/mac80211/wme.h +@@ -16,6 +16,8 @@ + u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb, + struct ieee80211_hdr *hdr); ++u16 __ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, ++ struct sta_info *sta, struct sk_buff *skb); + u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb); + void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, -- 2.30.2