mac80211: improve performance by deferring tx queue selection
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
		| @@ -0,0 +1,183 @@ | |||||||
|  | From: Felix Fietkau <nbd@nbd.name> | ||||||
|  | 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 <nbd@nbd.name> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- 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, | ||||||
		Reference in New Issue
	
	Block a user
	 Felix Fietkau
					Felix Fietkau