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

Commit b6da911b authored by Liad Kaufman's avatar Liad Kaufman Committed by Johannes Berg
Browse files

mac80211: synchronously reserve TID per station



In TDLS (e.g., TDLS off-channel) there is a requirement for
some drivers to supply an unused TID between the AP and the
device to the FW, to allow sending PTI requests and to allow
the FW to aggregate on a specific TID for better throughput.

To ensure that the allocated TID is indeed unused, this patch
introduces an API for blocking the driver from TXing on that
TID.

Signed-off-by: default avatarLiad Kaufman <liad.kaufman@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 4f9610d5
Loading
Loading
Loading
Loading
+37 −0
Original line number Original line Diff line number Diff line
@@ -5070,6 +5070,43 @@ void ieee80211_tdls_oper_request(struct ieee80211_vif *vif, const u8 *peer,
				 enum nl80211_tdls_operation oper,
				 enum nl80211_tdls_operation oper,
				 u16 reason_code, gfp_t gfp);
				 u16 reason_code, gfp_t gfp);


/**
 * ieee80211_reserve_tid - request to reserve a specific TID
 *
 * There is sometimes a need (such as in TDLS) for blocking the driver from
 * using a specific TID so that the FW can use it for certain operations such
 * as sending PTI requests. To make sure that the driver doesn't use that TID,
 * this function must be called as it flushes out packets on this TID and marks
 * it as blocked, so that any transmit for the station on this TID will be
 * redirected to the alternative TID in the same AC.
 *
 * Note that this function blocks and may call back into the driver, so it
 * should be called without driver locks held. Also note this function should
 * only be called from the driver's @sta_state callback.
 *
 * @sta: the station to reserve the TID for
 * @tid: the TID to reserve
 *
 * Returns: 0 on success, else on failure
 */
int ieee80211_reserve_tid(struct ieee80211_sta *sta, u8 tid);

/**
 * ieee80211_unreserve_tid - request to unreserve a specific TID
 *
 * Once there is no longer any need for reserving a certain TID, this function
 * should be called, and no longer will packets have their TID modified for
 * preventing use of this TID in the driver.
 *
 * Note that this function blocks and acquires a lock, so it should be called
 * without driver locks held. Also note this function should only be called
 * from the driver's @sta_state callback.
 *
 * @sta: the station
 * @tid: the TID to unreserve
 */
void ieee80211_unreserve_tid(struct ieee80211_sta *sta, u8 tid);

/**
/**
 * ieee80211_ie_split - split an IE buffer according to ordering
 * ieee80211_ie_split - split an IE buffer according to ordering
 *
 *
+7 −0
Original line number Original line Diff line number Diff line
@@ -509,6 +509,10 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
	struct tid_ampdu_tx *tid_tx;
	struct tid_ampdu_tx *tid_tx;
	int ret = 0;
	int ret = 0;


	if (WARN(sta->reserved_tid == tid,
		 "Requested to start BA session on reserved tid=%d", tid))
		return -EINVAL;

	trace_api_start_tx_ba_session(pubsta, tid);
	trace_api_start_tx_ba_session(pubsta, tid);


	if (WARN_ON_ONCE(!local->ops->ampdu_action))
	if (WARN_ON_ONCE(!local->ops->ampdu_action))
@@ -765,6 +769,9 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
		goto unlock;
		goto unlock;
	}
	}


	WARN(sta->reserved_tid == tid,
	     "Requested to stop BA session on reserved tid=%d", tid);

	if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
	if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
		/* already in progress stopping it */
		/* already in progress stopping it */
		ret = 0;
		ret = 0;
+1 −0
Original line number Original line Diff line number Diff line
@@ -1011,6 +1011,7 @@ enum queue_stop_reason {
	IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL,
	IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL,
	IEEE80211_QUEUE_STOP_REASON_FLUSH,
	IEEE80211_QUEUE_STOP_REASON_FLUSH,
	IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN,
	IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN,
	IEEE80211_QUEUE_STOP_REASON_RESERVE_TID,


	IEEE80211_QUEUE_STOP_REASONS,
	IEEE80211_QUEUE_STOP_REASONS,
};
};
+3 −0
Original line number Original line Diff line number Diff line
@@ -351,6 +351,9 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,


	sta->sta_state = IEEE80211_STA_NONE;
	sta->sta_state = IEEE80211_STA_NONE;


	/* Mark TID as unreserved */
	sta->reserved_tid = IEEE80211_TID_UNRESERVED;

	ktime_get_ts(&uptime);
	ktime_get_ts(&uptime);
	sta->last_connected = uptime.tv_sec;
	sta->last_connected = uptime.tv_sec;
	ewma_init(&sta->avg_signal, 1024, 8);
	ewma_init(&sta->avg_signal, 1024, 8);
+6 −0
Original line number Original line Diff line number Diff line
@@ -254,6 +254,9 @@ struct ieee80211_tx_latency_stat {
	u32 bin_count;
	u32 bin_count;
};
};


/* Value to indicate no TID reservation */
#define IEEE80211_TID_UNRESERVED	0xff

/**
/**
 * struct sta_info - STA information
 * struct sta_info - STA information
 *
 *
@@ -342,6 +345,7 @@ struct ieee80211_tx_latency_stat {
 *	AP only.
 *	AP only.
 * @cipher_scheme: optional cipher scheme for this station
 * @cipher_scheme: optional cipher scheme for this station
 * @last_tdls_pkt_time: holds the time in jiffies of last TDLS pkt ACKed
 * @last_tdls_pkt_time: holds the time in jiffies of last TDLS pkt ACKed
 * @reserved_tid: reserved TID (if any, otherwise IEEE80211_TID_UNRESERVED)
 */
 */
struct sta_info {
struct sta_info {
	/* General information, mostly static */
	/* General information, mostly static */
@@ -459,6 +463,8 @@ struct sta_info {
	/* TDLS timeout data */
	/* TDLS timeout data */
	unsigned long last_tdls_pkt_time;
	unsigned long last_tdls_pkt_time;


	u8 reserved_tid;

	/* keep last! */
	/* keep last! */
	struct ieee80211_sta sta;
	struct ieee80211_sta sta;
};
};
Loading