git: c8dafefaee00 - main - LinuxKPI: 802.11 Refine/add DTIM/TSF handling

From: Bjoern A. Zeeb <bz_at_FreeBSD.org>
Date: Sat, 15 Jan 2022 22:32:38 UTC
The branch main has been updated by bz:

URL: https://cgit.FreeBSD.org/src/commit/?id=c8dafefaee00d5741ea141f4f7514811437add06

commit c8dafefaee00d5741ea141f4f7514811437add06
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2022-01-15 22:22:30 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2022-01-15 22:22:30 +0000

    LinuxKPI: 802.11 Refine/add DTIM/TSF handling
    
    Correct data types related to delivery traffic indication map (DTIM)/
    timing synchronization function (TSF) and implement/refine their
    handling.  This information is used/needed by iwlwifi to set a station
    as associated.  This will hopefully avoid more "no beacon heard"
    time event failures.
    
    The recording of the Linux specific sync_device_ts is done in the
    receive path for now in case we do have the right information
    available.  I need to investigate as to how-much it may make sense
    to also migrate it into net80211 in the future depending on the
    usage in other drivers (or how we did handle this in the past in
    natively ported versions, e.g. iwm).
    
    Sponsored by:   The FreeBSD Foundation
    MFC after:      3 days
---
 sys/compat/linuxkpi/common/include/net/mac80211.h | 46 ++++++++++++-----------
 sys/compat/linuxkpi/common/src/linux_80211.c      | 40 ++++++++++++++++++--
 2 files changed, 61 insertions(+), 25 deletions(-)

diff --git a/sys/compat/linuxkpi/common/include/net/mac80211.h b/sys/compat/linuxkpi/common/include/net/mac80211.h
index 15ad25cf3a19..4c558e42da24 100644
--- a/sys/compat/linuxkpi/common/include/net/mac80211.h
+++ b/sys/compat/linuxkpi/common/include/net/mac80211.h
@@ -186,9 +186,9 @@ struct ieee80211_bss_conf {
 	size_t					ssid_len;
 	uint8_t					ssid[IEEE80211_NWID_LEN];
 	uint16_t				aid;
-	uint16_t				beacon_int;
 	uint16_t				ht_operation_mode;
 	int					arp_addr_cnt;
+
 	uint8_t					dtim_period;
 	bool					assoc;
 	bool					idle;
@@ -198,12 +198,16 @@ struct ieee80211_bss_conf {
 	bool					use_cts_prot;
 	bool					use_short_preamble;
 	bool					use_short_slot;
+	uint16_t				beacon_int;
+	uint32_t				sync_device_ts;
+	uint64_t				sync_tsf;
+	uint8_t					sync_dtim_count;
+	int16_t					txpower;
 
-	int		txpower;
 	int		ack_enabled, bssid_index, bssid_indicator, cqm_rssi_hyst, cqm_rssi_thold, ema_ap, frame_time_rts_th, ftm_responder;
 	int		htc_trig_based_pkt_ext;
 	int		multi_sta_back_32bit, nontransmitted;
-	int		profile_periodicity, sync_device_ts, sync_dtim_count, sync_tsf;
+	int		profile_periodicity;
 	int		twt_requester, uora_exists, uora_ocw_range;
 	int		assoc_capability, enable_beacon, hidden_ssid, ibss_joined, mcast_rate, twt_protected;
 	unsigned long	basic_rates;
@@ -446,34 +450,34 @@ enum ieee80211_rx_status_flags {
 
 struct ieee80211_rx_status {
 	/* TODO FIXME, this is too large. Over-reduce types to u8 where possible. */
-	u8	boottime_ns;
-	u8	mactime;
-	u8	device_timestamp;
+	uint64_t			boottime_ns;
+	uint64_t			mactime;
+	uint32_t			device_timestamp;
 	enum ieee80211_rx_status_flags	flag;
-	u16	freq;
-	u8	bw;
+	uint16_t			freq;
+	uint8_t				bw;
 #define	RATE_INFO_BW_20		0x01
 #define	RATE_INFO_BW_40		0x02
 #define	RATE_INFO_BW_80		0x04
 #define	RATE_INFO_BW_160	0x08
 #define	RATE_INFO_BW_HE_RU	0x10
-	u8	encoding;
+	uint8_t				encoding;
 #define	RX_ENC_LEGACY		0x00
 #define	RX_ENC_HE		0x01
 #define	RX_ENC_HT		0x02
 #define	RX_ENC_VHT		0x04
-	u8	ampdu_reference;
-	u8	band;
-	u8	chains;
-	u8	chain_signal[3];
-	u8	signal;
-	u8	enc_flags;
-	u8	he_dcm;
-	u8	he_gi;
-	u8	he_ru;
-	u8	zero_length_psdu_type;
-	uint8_t		nss;
-	uint8_t		rate_idx;
+	uint8_t				ampdu_reference;
+	uint8_t				band;
+	uint8_t				chains;
+	uint8_t				chain_signal[4];
+	uint8_t				signal;
+	uint8_t				enc_flags;
+	uint8_t				he_dcm;
+	uint8_t				he_gi;
+	uint8_t				he_ru;
+	uint8_t				zero_length_psdu_type;
+	uint8_t				nss;
+	uint8_t				rate_idx;
 };
 
 struct ieee80211_scan_ies {
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c
index 8eabf63d43d7..beb2b03f0498 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -779,6 +779,12 @@ lkpi_sta_scan_to_auth(struct ieee80211vap *vap, enum ieee80211_state nstate, int
 	if (vif->bss_conf.beacon_int < 16)
 		vif->bss_conf.beacon_int = 16;
 	bss_changed |= BSS_CHANGED_BEACON_INT;
+	vif->bss_conf.dtim_period = vap->iv_dtim_period;
+	bss_changed |= BSS_CHANGED_BEACON_INFO;
+	vif->bss_conf.sync_dtim_count = vap->iv_dtim_count;
+	vif->bss_conf.sync_tsf = le64toh(ni->ni_tstamp.tsf);
+	/* vif->bss_conf.sync_device_ts = set in linuxkpi_ieee80211_rx. */
+
 	/* Should almost assert it is this. */
 	vif->bss_conf.assoc = false;
 	vif->bss_conf.aid = 0;
@@ -3077,7 +3083,6 @@ linuxkpi_ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
 	struct ieee80211_rx_stats rx_stats;
 	struct ieee80211_node *ni;
 	struct ieee80211vap *vap;
-	struct ieee80211_frame_min *wh;
 	struct ieee80211_hdr *hdr;
 	struct lkpi_sta *lsta;
 	int i, offset, ok, type;
@@ -3127,11 +3132,11 @@ linuxkpi_ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
 
 	/* Implement a dump_rxcb() !!! */
 	if (debug_80211 & D80211_TRACE_RX)
-		printf("TRACE %s: RXCB: %u %u %u, %#0x, %u, %#0x, %#0x, "
+		printf("TRACE %s: RXCB: %ju %ju %u, %#0x, %u, %#0x, %#0x, "
 		    "%u band %u, %u %u %u %u, %u, %#x %#x %#x %#x %u %u %u\n",
 			__func__,
-			rx_status->boottime_ns,
-			rx_status->mactime,
+			(uintmax_t)rx_status->boottime_ns,
+			(uintmax_t)rx_status->mactime,
 			rx_status->device_timestamp,
 			rx_status->flag,
 			rx_status->freq,
@@ -3186,6 +3191,8 @@ no_trace_beacons:
 		lsta = STA_TO_LSTA(sta);
 		ni = ieee80211_ref_node(lsta->ni);
 	} else {
+		struct ieee80211_frame_min *wh;
+
 		wh = mtod(m, struct ieee80211_frame_min *);
 		ni = ieee80211_find_rxnode(ic, wh);
 		if (ni != NULL)
@@ -3204,6 +3211,31 @@ no_trace_beacons:
 	if (debug_80211 & D80211_TRACE_RX)
 		printf("TRACE %s: sta %p lsta %p ni %p vap %p\n", __func__, sta, lsta, ni, vap);
 
+	if (ni != NULL && vap != NULL &&
+	    ieee80211_is_beacon(hdr->frame_control) &&
+	    rx_status->device_timestamp > 0 &&
+	    m->m_pkthdr.len >= sizeof(struct ieee80211_frame)) {
+		struct lkpi_vif *lvif;
+		struct ieee80211_vif *vif;
+		struct ieee80211_frame *wh;
+
+		wh = mtod(m, struct ieee80211_frame *);
+		if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid))
+			goto skip_device_ts;
+
+		lvif = VAP_TO_LVIF(vap);
+		vif = LVIF_TO_VIF(lvif);
+
+		IMPROVE("TIMING_BEACON_ONLY?");
+		/* mac80211 specific (not net80211) so keep it here. */
+		vif->bss_conf.sync_device_ts = rx_status->device_timestamp;
+		/*
+		 * net80211 should take care of the other information (sync_tsf,
+		 * sync_dtim_count) as otherwise we need to parse the beacon.
+		 */
+	}
+skip_device_ts:
+
 	if (vap != NULL && vap->iv_state > IEEE80211_S_INIT &&
 	    ieee80211_radiotap_active_vap(vap)) {
 		struct lkpi_radiotap_rx_hdr *rtap;