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

Commit 41cbb0f5 authored by Luca Coelho's avatar Luca Coelho Committed by Johannes Berg
Browse files

mac80211: add support for HE



Add support for HE in mac80211 conforming with P802.11ax_D1.4.

Johannes: Fix another bug with the buf_size comparison in agg-rx.c.

Signed-off-by: default avatarLiad Kaufman <liad.kaufman@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarIlan Peer <ilan.peer@intel.com>
Signed-off-by: default avatarIdo Yariv <idox.yariv@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent b8042b3d
Loading
Loading
Loading
Loading
+55 −9
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <linux/ieee80211.h>
#include <net/cfg80211.h>
#include <net/codel.h>
#include <net/ieee80211_radiotap.h>
#include <asm/unaligned.h>

/**
@@ -162,6 +163,8 @@ enum ieee80211_ac_numbers {
 * @txop: maximum burst time in units of 32 usecs, 0 meaning disabled
 * @acm: is mandatory admission control required for the access category
 * @uapsd: is U-APSD mode enabled for the queue
 * @mu_edca: is the MU EDCA configured
 * @mu_edca_param_rec: MU EDCA Parameter Record for HE
 */
struct ieee80211_tx_queue_params {
	u16 txop;
@@ -170,6 +173,8 @@ struct ieee80211_tx_queue_params {
	u8 aifs;
	bool acm;
	bool uapsd;
	bool mu_edca;
	struct ieee80211_he_mu_edca_param_ac_rec mu_edca_param_rec;
};

struct ieee80211_low_level_stats {
@@ -463,6 +468,15 @@ struct ieee80211_mu_group_data {
 * This structure keeps information about a BSS (and an association
 * to that BSS) that can change during the lifetime of the BSS.
 *
 * @bss_color: 6-bit value to mark inter-BSS frame, if BSS supports HE
 * @htc_trig_based_pkt_ext: default PE in 4us units, if BSS supports HE
 * @multi_sta_back_32bit: supports BA bitmap of 32-bits in Multi-STA BACK
 * @uora_exists: is the UORA element advertised by AP
 * @ack_enabled: indicates support to receive a multi-TID that solicits either
 *	ACK, BACK or both
 * @uora_ocw_range: UORA element's OCW Range field
 * @frame_time_rts_th: HE duration RTS threshold, in units of 32us
 * @he_support: does this BSS support HE
 * @assoc: association status
 * @ibss_joined: indicates whether this station is part of an IBSS
 *	or not
@@ -550,6 +564,14 @@ struct ieee80211_mu_group_data {
 */
struct ieee80211_bss_conf {
	const u8 *bssid;
	u8 bss_color;
	u8 htc_trig_based_pkt_ext;
	bool multi_sta_back_32bit;
	bool uora_exists;
	bool ack_enabled;
	u8 uora_ocw_range;
	u16 frame_time_rts_th;
	bool he_support;
	/* association related data */
	bool assoc, ibss_joined;
	bool ibss_creator;
@@ -1106,6 +1128,18 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
 * @RX_FLAG_AMPDU_EOF_BIT: Value of the EOF bit in the A-MPDU delimiter for this
 *	frame
 * @RX_FLAG_AMPDU_EOF_BIT_KNOWN: The EOF value is known
 * @RX_FLAG_RADIOTAP_HE: HE radiotap data is present
 *	(&struct ieee80211_radiotap_he, mac80211 will fill in
 *	 - DATA3_DATA_MCS
 *	 - DATA3_DATA_DCM
 *	 - DATA3_CODING
 *	 - DATA5_GI
 *	 - DATA5_DATA_BW_RU_ALLOC
 *	 - DATA6_NSTS
 *	 - DATA3_STBC
 *	from the RX info data, so leave those zeroed when building this data)
 * @RX_FLAG_RADIOTAP_HE_MU: HE MU radiotap data is present
 *	(&struct ieee80211_radiotap_he_mu)
 */
enum mac80211_rx_flags {
	RX_FLAG_MMIC_ERROR		= BIT(0),
@@ -1134,6 +1168,8 @@ enum mac80211_rx_flags {
	RX_FLAG_ICV_STRIPPED		= BIT(23),
	RX_FLAG_AMPDU_EOF_BIT		= BIT(24),
	RX_FLAG_AMPDU_EOF_BIT_KNOWN	= BIT(25),
	RX_FLAG_RADIOTAP_HE		= BIT(26),
	RX_FLAG_RADIOTAP_HE_MU		= BIT(27),
};

/**
@@ -1164,6 +1200,7 @@ enum mac80211_rx_encoding {
	RX_ENC_LEGACY = 0,
	RX_ENC_HT,
	RX_ENC_VHT,
	RX_ENC_HE,
};

/**
@@ -1198,6 +1235,9 @@ enum mac80211_rx_encoding {
 * @encoding: &enum mac80211_rx_encoding
 * @bw: &enum rate_info_bw
 * @enc_flags: uses bits from &enum mac80211_rx_encoding_flags
 * @he_ru: HE RU, from &enum nl80211_he_ru_alloc
 * @he_gi: HE GI, from &enum nl80211_he_gi
 * @he_dcm: HE DCM value
 * @rx_flags: internal RX flags for mac80211
 * @ampdu_reference: A-MPDU reference number, must be a different value for
 *	each A-MPDU but the same for each subframe within one A-MPDU
@@ -1211,7 +1251,8 @@ struct ieee80211_rx_status {
	u32 flag;
	u16 freq;
	u8 enc_flags;
	u8 encoding:2, bw:3;
	u8 encoding:2, bw:3, he_ru:3;
	u8 he_gi:2, he_dcm:1;
	u8 rate_idx;
	u8 nss;
	u8 rx_flags;
@@ -1770,6 +1811,7 @@ struct ieee80211_sta_rates {
 * @supp_rates: Bitmap of supported rates (per band)
 * @ht_cap: HT capabilities of this STA; restricted to our own capabilities
 * @vht_cap: VHT capabilities of this STA; restricted to our own capabilities
 * @he_cap: HE capabilities of this STA
 * @max_rx_aggregation_subframes: maximal amount of frames in a single AMPDU
 *	that this station is allowed to transmit to us.
 *	Can be modified by driver.
@@ -1805,7 +1847,8 @@ struct ieee80211_sta {
	u16 aid;
	struct ieee80211_sta_ht_cap ht_cap;
	struct ieee80211_sta_vht_cap vht_cap;
	u8 max_rx_aggregation_subframes;
	struct ieee80211_sta_he_cap he_cap;
	u16 max_rx_aggregation_subframes;
	bool wme;
	u8 uapsd_queues;
	u8 max_sp;
@@ -2196,10 +2239,11 @@ enum ieee80211_hw_flags {
 *	it shouldn't be set.
 *
 * @max_tx_aggregation_subframes: maximum number of subframes in an
 *	aggregate an HT driver will transmit. Though ADDBA will advertise
 *	a constant value of 64 as some older APs can crash if the window
 *	size is smaller (an example is LinkSys WRT120N with FW v1.0.07
 *	build 002 Jun 18 2012).
 *	aggregate an HT/HE device will transmit. In HT AddBA we'll
 *	advertise a constant value of 64 as some older APs crash if
 *	the window size is smaller (an example is LinkSys WRT120N
 *	with FW v1.0.07 build 002 Jun 18 2012).
 *	For AddBA to HE capable peers this value will be used.
 *
 * @max_tx_fragments: maximum number of tx buffers per (A)-MSDU, sum
 *	of 1 + skb_shinfo(skb)->nr_frags for each skb in the frag_list.
@@ -2216,6 +2260,8 @@ enum ieee80211_hw_flags {
 *	the default is _GI | _BANDWIDTH.
 *	Use the %IEEE80211_RADIOTAP_VHT_KNOWN_\* values.
 *
 * @radiotap_he: HE radiotap validity flags
 *
 * @radiotap_timestamp: Information for the radiotap timestamp field; if the
 *	'units_pos' member is set to a non-negative value it must be set to
 *	a combination of a IEEE80211_RADIOTAP_TIMESTAMP_UNIT_* and a
@@ -2263,8 +2309,8 @@ struct ieee80211_hw {
	u8 max_rates;
	u8 max_report_rates;
	u8 max_rate_tries;
	u8 max_rx_aggregation_subframes;
	u8 max_tx_aggregation_subframes;
	u16 max_rx_aggregation_subframes;
	u16 max_tx_aggregation_subframes;
	u8 max_tx_fragments;
	u8 offchannel_tx_hw_queue;
	u8 radiotap_mcs_details;
@@ -2904,7 +2950,7 @@ struct ieee80211_ampdu_params {
	struct ieee80211_sta *sta;
	u16 tid;
	u16 ssn;
	u8 buf_size;
	u16 buf_size;
	bool amsdu;
	u16 timeout;
};
+1 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ mac80211-y := \
	scan.o offchannel.o \
	ht.o agg-tx.o agg-rx.o \
	vht.o \
	he.o \
	ibss.o \
	iface.o \
	rate.o \
+8 −2
Original line number Diff line number Diff line
@@ -245,6 +245,7 @@ void ___ieee80211_start_rx_ba_session(struct sta_info *sta,
	};
	int i, ret = -EOPNOTSUPP;
	u16 status = WLAN_STATUS_REQUEST_DECLINED;
	u16 max_buf_size;

	if (tid >= IEEE80211_FIRST_TSPEC_TSID) {
		ht_dbg(sta->sdata,
@@ -268,13 +269,18 @@ void ___ieee80211_start_rx_ba_session(struct sta_info *sta,
		goto end;
	}

	if (sta->sta.he_cap.has_he)
		max_buf_size = IEEE80211_MAX_AMPDU_BUF;
	else
		max_buf_size = IEEE80211_MAX_AMPDU_BUF_HT;

	/* sanity check for incoming parameters:
	 * check if configuration can support the BA policy
	 * and if buffer size does not exceeds max value */
	/* XXX: check own ht delayed BA capability?? */
	if (((ba_policy != 1) &&
	     (!(sta->sta.ht_cap.cap & IEEE80211_HT_CAP_DELAY_BA))) ||
	    (buf_size > IEEE80211_MAX_AMPDU_BUF_HT)) {
	    (buf_size > max_buf_size)) {
		status = WLAN_STATUS_INVALID_QOS_PARAM;
		ht_dbg_ratelimited(sta->sdata,
				   "AddBA Req with bad params from %pM on tid %u. policy %d, buffer size %d\n",
@@ -283,7 +289,7 @@ void ___ieee80211_start_rx_ba_session(struct sta_info *sta,
	}
	/* determine default buffer size */
	if (buf_size == 0)
		buf_size = IEEE80211_MAX_AMPDU_BUF_HT;
		buf_size = max_buf_size;

	/* make sure the size doesn't exceed the maximum supported by the hw */
	if (buf_size > sta->sta.max_rx_aggregation_subframes)
+15 −4
Original line number Diff line number Diff line
@@ -463,6 +463,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
		.timeout = 0,
	};
	int ret;
	u16 buf_size;

	tid_tx = rcu_dereference_protected_tid_tx(sta, tid);

@@ -511,11 +512,22 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
	sta->ampdu_mlme.addba_req_num[tid]++;
	spin_unlock_bh(&sta->lock);

	if (sta->sta.he_cap.has_he) {
		buf_size = local->hw.max_tx_aggregation_subframes;
	} else {
		/*
		 * We really should use what the driver told us it will
		 * transmit as the maximum, but certain APs (e.g. the
		 * LinkSys WRT120N with FW v1.0.07 build 002 Jun 18 2012)
		 * will crash when we use a lower number.
		 */
		buf_size = IEEE80211_MAX_AMPDU_BUF_HT;
	}

	/* send AddBA request */
	ieee80211_send_addba_request(sdata, sta->sta.addr, tid,
				     tid_tx->dialog_token, params.ssn,
				     IEEE80211_MAX_AMPDU_BUF_HT,
				     tid_tx->timeout);
				     buf_size, tid_tx->timeout);
}

/*
@@ -905,8 +917,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
{
	struct tid_ampdu_tx *tid_tx;
	struct ieee80211_txq *txq;
	u16 capab, tid;
	u8 buf_size;
	u16 capab, tid, buf_size;
	bool amsdu;

	capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
+5 −0
Original line number Diff line number Diff line
@@ -1412,6 +1412,11 @@ static int sta_apply_parameters(struct ieee80211_local *local,
		ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
						    params->vht_capa, sta);

	if (params->he_capa)
		ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband,
						  (void *)params->he_capa,
						  params->he_capa_len, sta);

	if (params->opmode_notif_used) {
		/* returned value is only needed for rc update, but the
		 * rc isn't initialized here yet, so ignore it
Loading