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

Commit adf8ed01 authored by Johannes Berg's avatar Johannes Berg
Browse files

mac80211: add an optional TXQ for other PS-buffered frames



Some drivers may want to also use the TXQ abstraction with
non-data packets that need powersave buffering, so add a
hardware flag to allow this.

Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 331aead5
Loading
Loading
Loading
Loading
+12 −5
Original line number Diff line number Diff line
@@ -101,8 +101,9 @@
 * Drivers indicate that they use this model by implementing the .wake_tx_queue
 * driver operation.
 *
 * Intermediate queues (struct ieee80211_txq) are kept per-sta per-tid, with a
 * single per-vif queue for multicast data frames.
 * Intermediate queues (struct ieee80211_txq) are kept per-sta per-tid, with
 * another per-sta for non-data/non-mgmt and bufferable management frames, and
 * a single per-vif queue for multicast data frames.
 *
 * The driver is expected to initialize its private per-queue data for stations
 * and interfaces in the .add_interface and .sta_add ops.
@@ -1843,7 +1844,8 @@ struct ieee80211_sta_rates {
 *	unlimited.
 * @support_p2p_ps: indicates whether the STA supports P2P PS mechanism or not.
 * @max_rc_amsdu_len: Maximum A-MSDU size in bytes recommended by rate control.
 * @txq: per-TID data TX queues (if driver uses the TXQ abstraction)
 * @txq: per-TID data TX queues (if driver uses the TXQ abstraction); note that
 *	the last entry (%IEEE80211_NUM_TIDS) is used for non-data frames
 */
struct ieee80211_sta {
	u32 supp_rates[NUM_NL80211_BANDS];
@@ -1884,7 +1886,7 @@ struct ieee80211_sta {
	bool support_p2p_ps;
	u16 max_rc_amsdu_len;

	struct ieee80211_txq *txq[IEEE80211_NUM_TIDS];
	struct ieee80211_txq *txq[IEEE80211_NUM_TIDS + 1];

	/* must be last */
	u8 drv_priv[0] __aligned(sizeof(void *));
@@ -1918,7 +1920,8 @@ struct ieee80211_tx_control {
 *
 * @vif: &struct ieee80211_vif pointer from the add_interface callback.
 * @sta: station table entry, %NULL for per-vif queue
 * @tid: the TID for this queue (unused for per-vif queue)
 * @tid: the TID for this queue (unused for per-vif queue),
 *	%IEEE80211_NUM_TIDS for non-data (if enabled)
 * @ac: the AC for this queue
 * @drv_priv: driver private area, sized by hw->txq_data_size
 *
@@ -2131,6 +2134,9 @@ struct ieee80211_txq {
 * @IEEE80211_HW_DOESNT_SUPPORT_QOS_NDP: The driver (or firmware) doesn't
 *	support QoS NDP for AP probing - that's most likely a driver bug.
 *
 * @IEEE80211_HW_BUFF_MMPDU_TXQ: use the TXQ for bufferable MMPDUs, this of
 *	course requires the driver to use TXQs to start with.
 *
 * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
 */
enum ieee80211_hw_flags {
@@ -2176,6 +2182,7 @@ enum ieee80211_hw_flags {
	IEEE80211_HW_SUPPORTS_TDLS_BUFFER_STA,
	IEEE80211_HW_DEAUTH_NEED_MGD_TX_PREP,
	IEEE80211_HW_DOESNT_SUPPORT_QOS_NDP,
	IEEE80211_HW_BUFF_MMPDU_TXQ,

	/* keep last, obviously */
	NUM_IEEE80211_HW_FLAGS
+2 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
 *
 * Copyright 2007	Johannes Berg <johannes@sipsolutions.net>
 * Copyright 2013-2014  Intel Mobile Communications GmbH
 * Copyright (C) 2018 Intel Corporation
 *
 * GPLv2
 *
@@ -214,6 +215,7 @@ static const char *hw_flag_names[] = {
	FLAG(SUPPORTS_TDLS_BUFFER_STA),
	FLAG(DEAUTH_NEED_MGD_TX_PREP),
	FLAG(DOESNT_SUPPORT_QOS_NDP),
	FLAG(BUFF_MMPDU_TXQ),
#undef FLAG
};

+4 −2
Original line number Diff line number Diff line
@@ -141,7 +141,7 @@ static ssize_t sta_aqm_read(struct file *file, char __user *userbuf,
{
	struct sta_info *sta = file->private_data;
	struct ieee80211_local *local = sta->local;
	size_t bufsz = AQM_TXQ_ENTRY_LEN*(IEEE80211_NUM_TIDS+1);
	size_t bufsz = AQM_TXQ_ENTRY_LEN * (IEEE80211_NUM_TIDS + 2);
	char *buf = kzalloc(bufsz, GFP_KERNEL), *p = buf;
	struct txq_info *txqi;
	ssize_t rv;
@@ -163,7 +163,9 @@ static ssize_t sta_aqm_read(struct file *file, char __user *userbuf,
		       bufsz+buf-p,
		       "tid ac backlog-bytes backlog-packets new-flows drops marks overlimit collisions tx-bytes tx-packets flags\n");

	for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
	for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
		if (!sta->sta.txq[i])
			continue;
		txqi = to_txq_info(sta->sta.txq[i]);
		p += scnprintf(p, bufsz+buf-p,
			       "%d %d %u %u %u %u %u %u %u %u %u 0x%lx(%s%s%s)\n",
+1 −1
Original line number Diff line number Diff line
@@ -1505,7 +1505,7 @@ static void sta_ps_start(struct sta_info *sta)
	if (!sta->sta.txq[0])
		return;

	for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) {
	for (tid = 0; tid < IEEE80211_NUM_TIDS; tid++) {
		if (txq_has_queue(sta->sta.txq[tid]))
			set_bit(tid, &sta->txq_buffered_tids);
		else
+13 −8
Original line number Diff line number Diff line
@@ -113,7 +113,12 @@ static void __cleanup_single_sta(struct sta_info *sta)

	if (sta->sta.txq[0]) {
		for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
			struct txq_info *txqi = to_txq_info(sta->sta.txq[i]);
			struct txq_info *txqi;

			if (!sta->sta.txq[i])
				continue;

			txqi = to_txq_info(sta->sta.txq[i]);

			spin_lock_bh(&fq->lock);
			ieee80211_txq_purge(local, txqi);
@@ -374,6 +379,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
		for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
			struct txq_info *txq = txq_data + i * size;

			/* might not do anything for the bufferable MMPDU TXQ */
			ieee80211_txq_init(sdata, sta, txq, i);
		}
	}
@@ -1239,14 +1245,12 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
	if (!ieee80211_hw_check(&local->hw, AP_LINK_PS))
		drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta);

	if (sta->sta.txq[0]) {
	for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
			if (!txq_has_queue(sta->sta.txq[i]))
		if (!sta->sta.txq[i] || !txq_has_queue(sta->sta.txq[i]))
			continue;

		drv_wake_tx_queue(local, to_txq_info(sta->sta.txq[i]));
	}
	}

	skb_queue_head_init(&pending);

@@ -1683,7 +1687,8 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
			return;

		for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) {
			if (!(driver_release_tids & BIT(tid)) ||
			if (!sta->sta.txq[tid] ||
			    !(driver_release_tids & BIT(tid)) ||
			    txq_has_queue(sta->sta.txq[tid]))
				continue;

Loading