Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fa962b92 authored by Michal Kazior's avatar Michal Kazior Committed by Johannes Berg
Browse files

mac80211: implement fair queueing per txq



mac80211's software queues were designed to work
very closely with device tx queues. They are
required to make use of 802.11 packet aggregation
easily and efficiently.

Due to the way 802.11 aggregation is designed it
only makes sense to keep fair queuing as close to
hardware as possible to reduce induced latency and
inertia and provide the best flow responsiveness.

This change doesn't translate directly to
immediate and significant gains. End result
depends on driver's induced latency. Best results
can be achieved if driver keeps its own tx
queue/fifo fill level to a minimum.

Signed-off-by: default avatarMichal Kazior <michal.kazior@tieto.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 80a83cfc
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -194,17 +194,21 @@ static void
ieee80211_agg_stop_txq(struct sta_info *sta, int tid)
{
	struct ieee80211_txq *txq = sta->sta.txq[tid];
	struct ieee80211_sub_if_data *sdata;
	struct fq *fq;
	struct txq_info *txqi;

	if (!txq)
		return;

	txqi = to_txq_info(txq);
	sdata = vif_to_sdata(txq->vif);
	fq = &sdata->local->fq;

	/* Lock here to protect against further seqno updates on dequeue */
	spin_lock_bh(&txqi->queue.lock);
	spin_lock_bh(&fq->lock);
	set_bit(IEEE80211_TXQ_STOP, &txqi->flags);
	spin_unlock_bh(&txqi->queue.lock);
	spin_unlock_bh(&fq->lock);
}

static void
+19 −5
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include <net/ieee80211_radiotap.h>
#include <net/cfg80211.h>
#include <net/mac80211.h>
#include <net/fq.h>
#include "key.h"
#include "sta_info.h"
#include "debug.h"
@@ -805,10 +806,17 @@ enum txq_info_flags {
	IEEE80211_TXQ_NO_AMSDU,
};

/**
 * struct txq_info - per tid queue
 *
 * @tin: contains packets split into multiple flows
 * @def_flow: used as a fallback flow when a packet destined to @tin hashes to
 *	a fq_flow which is already owned by a different tin
 */
struct txq_info {
	struct sk_buff_head queue;
	struct fq_tin tin;
	struct fq_flow def_flow;
	unsigned long flags;
	unsigned long byte_cnt;

	/* keep last! */
	struct ieee80211_txq txq;
@@ -1099,6 +1107,8 @@ struct ieee80211_local {
	 * it first anyway so they become a no-op */
	struct ieee80211_hw hw;

	struct fq fq;

	const struct ieee80211_ops *ops;

	/*
@@ -1931,9 +1941,13 @@ static inline bool ieee80211_can_run_worker(struct ieee80211_local *local)
	return true;
}

void ieee80211_init_tx_queue(struct ieee80211_sub_if_data *sdata,
int ieee80211_txq_setup_flows(struct ieee80211_local *local);
void ieee80211_txq_teardown_flows(struct ieee80211_local *local);
void ieee80211_txq_init(struct ieee80211_sub_if_data *sdata,
			struct sta_info *sta,
			struct txq_info *txq, int tid);
void ieee80211_txq_purge(struct ieee80211_local *local,
			 struct txq_info *txqi);
void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
			 u16 transaction, u16 auth_alg, u16 status,
			 const u8 *extra, size_t extra_len, const u8 *bssid,
+5 −7
Original line number Diff line number Diff line
@@ -779,6 +779,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
			      bool going_down)
{
	struct ieee80211_local *local = sdata->local;
	struct fq *fq = &local->fq;
	unsigned long flags;
	struct sk_buff *skb, *tmp;
	u32 hw_reconf_flags = 0;
@@ -976,13 +977,10 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,

	if (sdata->vif.txq) {
		struct txq_info *txqi = to_txq_info(sdata->vif.txq);
		int n = skb_queue_len(&txqi->queue);

		spin_lock_bh(&txqi->queue.lock);
		ieee80211_purge_tx_queue(&local->hw, &txqi->queue);
		atomic_sub(n, &sdata->num_tx_queued);
		txqi->byte_cnt = 0;
		spin_unlock_bh(&txqi->queue.lock);
		spin_lock_bh(&fq->lock);
		ieee80211_txq_purge(local, txqi);
		spin_unlock_bh(&fq->lock);
	}

	if (local->open_count == 0)
@@ -1792,7 +1790,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,

		if (txq_size) {
			txqi = netdev_priv(ndev) + size;
			ieee80211_init_tx_queue(sdata, NULL, txqi, 0);
			ieee80211_txq_init(sdata, NULL, txqi, 0);
		}

		sdata->dev = ndev;
+7 −0
Original line number Diff line number Diff line
@@ -1086,6 +1086,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)

	rtnl_unlock();

	result = ieee80211_txq_setup_flows(local);
	if (result)
		goto fail_flows;

#ifdef CONFIG_INET
	local->ifa_notifier.notifier_call = ieee80211_ifa_changed;
	result = register_inetaddr_notifier(&local->ifa_notifier);
@@ -1111,6 +1115,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
#if defined(CONFIG_INET) || defined(CONFIG_IPV6)
 fail_ifa:
#endif
	ieee80211_txq_teardown_flows(local);
 fail_flows:
	rtnl_lock();
	rate_control_deinitialize(local);
	ieee80211_remove_interfaces(local);
@@ -1169,6 +1175,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
	skb_queue_purge(&local->skb_queue);
	skb_queue_purge(&local->skb_queue_unreliable);
	skb_queue_purge(&local->skb_queue_tdls_chsw);
	ieee80211_txq_teardown_flows(local);

	destroy_workqueue(local->workqueue);
	wiphy_unregister(local->hw.wiphy);
+1 −1
Original line number Diff line number Diff line
@@ -1268,7 +1268,7 @@ static void sta_ps_start(struct sta_info *sta)
	for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) {
		struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]);

		if (!skb_queue_len(&txqi->queue))
		if (!txqi->tin.backlog_packets)
			set_bit(tid, &sta->txq_buffered_tids);
		else
			clear_bit(tid, &sta->txq_buffered_tids);
Loading