wlan-ap-Telecominfraproject/feeds/wifi-ax/mac80211/patches/qca/349-ath11k-add-tx-delay-to-tsf.patch
John Crispin d29c4e49b3 mac80211-qsdk: update to ath11.5-cs
Signed-off-by: John Crispin <john@phrozen.org>
2022-05-17 07:45:32 +02:00

308 lines
9.7 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 24f8df5c39e1e1a3cdcf1af80560da34438205aa Mon Sep 17 00:00:00 2001
From: Hari Chandrakanthan <quic_haric@quicinc.com>
Date: Fri, 4 Mar 2022 23:00:18 +0530
Subject: [PATCH] ath11k: add tx delay to tsf
An AP sending a beacon frame shall set the value of the beacon frames
timestamp so that it equals the value of the STAs TSF timer at the
time that the data symbol containing the first bit of the timestamp
is transmitted to the PHY plus the transmitting STAs delays through
its local PHY from the MAC-PHY interface to its interface with the WM.
With this fix, tsf of beacon % beacon interval is greater than or equal
to the minimum value provided in the spec.
tx delay for 5G/6G:
20(lsig)+2(service)+32(6mbps, 24 bytes) = 54us + 2us(MAC/BB DELAY)
tx delay for 2.4G:
144 us ( LPREAMBLE) + 48 (PLCP Header) + 192 (1Mbps, 24 ytes)
= 384 us + 2us(MAC/BB DELAY
Signed-off-by: Hari Chandrakanthan <quic_haric@quicinc.com>
---
drivers/net/wireless/ath/ath11k/core.h | 1 +
drivers/net/wireless/ath/ath11k/mac.c | 20 ++++-
drivers/net/wireless/ath/ath11k/mac.h | 1 +
drivers/net/wireless/ath/ath11k/wmi.c | 134 ++++++++++++++++++++++++++++++++-
drivers/net/wireless/ath/ath11k/wmi.h | 18 +++++
5 files changed, 172 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index 8d7ab86..08403d9 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -369,6 +369,7 @@ struct ath11k_vif {
u32 tid_conf_changed[ATH11K_TID_MAX];
struct ath11k_tid_qos_config tid_cfg[ATH11K_TID_MAX];
u32 tids_rst;
+ u64 tbtt_offset;
DECLARE_BITMAP(free_groupidx_map, ATH11K_GROUP_KEYS_NUM_MAX);
};
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 6f473e1..d9404b8 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -1230,6 +1230,7 @@ static int __ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif, struct sk_buff
u8 *ies;
int ret;
const u8 *vht_cap_ie;
+ u64 adjusted_tsf;
ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn);
ies += sizeof(mgmt->u.beacon);
@@ -1267,6 +1268,15 @@ static int __ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif, struct sk_buff
WMI_BEACON_EMA_PARAM_LAST_TMPL_SHIFT;
}
+ /* Make the TSF offset negative so beacons in the same
+ * staggered batch have the same TSF.
+ */
+ if (arvif->tbtt_offset) {
+ adjusted_tsf = cpu_to_le64(0ULL - arvif->tbtt_offset);
+ mgmt = (void *)bcn->data;
+ memcpy(&mgmt->u.beacon.timestamp, &adjusted_tsf, sizeof(adjusted_tsf));
+ }
+
ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn, ema_param);
if (ret)
@@ -1365,7 +1375,7 @@ static int ath11k_mac_setup_bcn_tmpl_legacy(struct ath11k_vif *arvif,
return ret;
}
-static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
+int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
{
struct ath11k_vif *pvif = arvif;
struct ath11k_vif *cvif = NULL;
@@ -6832,11 +6842,13 @@ static void ath11k_mac_op_tx(struct ieee80211_hw *hw,
u32 info_flags = info->flags;
struct ieee80211_sta *sta = control->sta;
struct ath11k_sta *arsta = NULL;
+ struct ieee80211_mgmt *mgmt;
bool is_prb_rsp;
u16 frm_type = 0;
u8 tid, *qos_ctl;
bool noack = false;
int ret;
+ u64 adjusted_tsf;
if (unlikely(test_bit(ATH11K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))) {
ieee80211_free_txskb(ar->hw, skb);
@@ -6856,6 +6868,12 @@ static void ath11k_mac_op_tx(struct ieee80211_hw *hw,
} else if (ieee80211_is_mgmt(hdr->frame_control)) {
frm_type = FIELD_GET(IEEE80211_FCTL_STYPE, hdr->frame_control);
is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control);
+ if (is_prb_rsp && arvif->tbtt_offset) {
+ mgmt = (struct ieee80211_mgmt *)skb->data;
+ adjusted_tsf = cpu_to_le64(0ULL - arvif->tbtt_offset);
+ memcpy(&mgmt->u.probe_resp.timestamp, &adjusted_tsf,
+ sizeof(adjusted_tsf));
+ }
ret = ath11k_mac_tx_over_wmi(ar, skb, is_prb_rsp);
if (ret) {
if (ret != -EBUSY)
diff --git a/drivers/net/wireless/ath/ath11k/mac.h b/drivers/net/wireless/ath/ath11k/mac.h
index 9decde2..475756a 100644
--- a/drivers/net/wireless/ath/ath11k/mac.h
+++ b/drivers/net/wireless/ath/ath11k/mac.h
@@ -176,4 +176,5 @@ bool ath11k_mac_sta_level_info(struct ath11k_vif *arvif, struct ieee80211_sta *s
void ath11k_mac_get_any_chandef_iter(struct ieee80211_hw *hw,
struct ieee80211_chanctx_conf *conf,
void *data);
+int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif);
#endif
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index d87069e..3a176f9 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -10211,6 +10211,126 @@ static void ath11k_wmi_tlv_cfr_cpature_phase_fixed_param(const void *ptr,
}
}
+static int ath11k_wmi_tbtt_offset_subtlv_parser(struct ath11k_base *ab, u16 tag,
+ u16 len, const void *ptr,
+ void *data)
+{
+ int ret;
+ struct ath11k *ar;
+ u64 tx_delay = 0;
+ struct wmi_tbtt_offset_info *tbtt_offset_info;
+ struct ieee80211_chanctx_conf *conf;
+ struct ath11k_vif *arvif;
+
+ tbtt_offset_info = (struct wmi_tbtt_offset_info *)ptr;
+
+ rcu_read_lock();
+ ar = ath11k_mac_get_ar_by_vdev_id(ab, tbtt_offset_info->vdev_id);
+ if (!ar) {
+ ath11k_warn(ab, "ar not found, vdev_id %d\n", tbtt_offset_info->vdev_id);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ arvif = ath11k_mac_get_arvif(ar, tbtt_offset_info->vdev_id);
+ if (!arvif) {
+ ath11k_warn(ab, "arvif not found, vdev_id %d\n",
+ tbtt_offset_info->vdev_id);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ if (!arvif->is_up || (arvif->vdev_type != WMI_VDEV_TYPE_AP)) {
+ ret = 0;
+ goto exit;
+ }
+
+ arvif->tbtt_offset = tbtt_offset_info->tbtt_offset;
+
+ conf = rcu_dereference(arvif->vif->chanctx_conf);
+ if (conf && conf->def.chan->band == NL80211_BAND_2GHZ) {
+ /* 1Mbps Beacon: */
+ /* 144 us ( LPREAMBLE) + 48 (PLCP Header)
+ * + 192 (1Mbps, 24 ytes)
+ * = 384 us + 2us(MAC/BB DELAY
+ */
+ tx_delay = 386;
+ } else if (conf && (conf->def.chan->band == NL80211_BAND_5GHZ ||
+ conf->def.chan->band == NL80211_BAND_6GHZ)) {
+ /* 6Mbps Beacon: */
+ /*20(lsig)+2(service)+32(6mbps, 24 bytes)
+ *= 54us + 2us(MAC/BB DELAY)
+ */
+ tx_delay = 56;
+ }
+ arvif->tbtt_offset -= tx_delay;
+
+ ret = ath11k_mac_setup_bcn_tmpl(arvif);
+
+ if (ret)
+ ath11k_warn(ab, "failed to submit beacon template: %d\n",
+ ret);
+exit:
+ rcu_read_unlock();
+ return ret;
+}
+
+static int ath11k_wmi_tbtt_offset_event_parser(struct ath11k_base *ab,
+ u16 tag, u16 len,
+ const void *ptr, void *data)
+{
+ int ret;
+
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "wmi tbtt offset event tag 0x%x of len %d rcvd\n",
+ tag, len);
+
+ if (tag == WMI_TAG_ARRAY_STRUCT) {
+ ret = ath11k_wmi_tlv_iter(ab, ptr, len,
+ ath11k_wmi_tbtt_offset_subtlv_parser,
+ data);
+ }
+
+ return ret;
+}
+
+static int ath11k_wmi_pull_tbtt_offset(struct ath11k_base *ab, struct sk_buff *skb,
+ struct wmi_tbtt_offset_ev_arg *arg)
+{
+ struct wmi_tbtt_offset_event *ev = NULL;
+ struct wmi_tbtt_offset_info tbtt_offset_info = {0};
+ struct wmi_tlv *tlv;
+ int ret;
+ u8 *ptr;
+ u16 tlv_tag;
+
+ ptr = skb->data;
+
+ if (skb->len < (sizeof(*ev) + TLV_HDR_SIZE)) {
+ ath11k_warn(ab, "wmi_tbtt_offset event size invalid\n");
+ return -EINVAL;
+ }
+
+ tlv = (struct wmi_tlv *)ptr;
+ tlv_tag = FIELD_GET(WMI_TLV_TAG, tlv->header);
+ ptr += sizeof(*tlv);
+
+ if (tlv_tag == WMI_TAG_TBTT_OFFSET_EXT_EVENT) {
+ ev = (struct wmi_tbtt_offset_event *)ptr;
+ } else {
+ ath11k_warn(ab, "tbtt event received with invalid tag\n");
+ return -EINVAL;
+ }
+
+ ret = ath11k_wmi_tlv_iter(ab, skb->data, skb->len,
+ ath11k_wmi_tbtt_offset_event_parser,
+ &tbtt_offset_info);
+ if (ret) {
+ ath11k_warn(ab, "failed to parse tbtt tlv %d\n", ret);
+ return -EINVAL;
+ }
+ return 0;
+}
+
static int ath11k_wmi_tlv_cfr_capture_evt_parse(struct ath11k_base *ab,
u16 tag, u16 len,
const void *ptr, void *data)
@@ -10255,6 +10375,16 @@ static void ath11k_wmi_parse_cfr_capture_event(struct ath11k_base *ab,
"failed to process cfr cpature ret = %d\n", ret);
}
+void ath11k_wmi_event_tbttoffset_update(struct ath11k_base *ab, struct sk_buff *skb)
+{
+ struct wmi_tbtt_offset_ev_arg arg = {};
+ int ret;
+
+ ret = ath11k_wmi_pull_tbtt_offset(ab, skb, &arg);
+ if (ret)
+ ath11k_warn(ab, "failed to parse tbtt offset event: %d\n", ret);
+}
+
static int ath11k_wmi_peer_ratecode_subtlv_parser(struct ath11k_base *ab,
u16 tag, u16 len,
const void *ptr, void *data)
@@ -10526,8 +10656,10 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
case WMI_OBSS_COLOR_COLLISION_DETECTION_EVENTID:
ath11k_wmi_obss_color_collision_event(ab, skb);
break;
- /* add Unsupported events here */
case WMI_TBTTOFFSET_EXT_UPDATE_EVENTID:
+ ath11k_wmi_event_tbttoffset_update(ab, skb);
+ break;
+ /* add Unsupported events here */
case WMI_PEER_OPER_MODE_CHANGE_EVENTID:
case WMI_TWT_ENABLE_EVENTID:
case WMI_TWT_DISABLE_EVENTID:
diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
index 95beb56..ecc42fc 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -4618,6 +4618,24 @@ struct wmi_vdev_delete_resp_event {
u32 vdev_id;
} __packed;
+struct wmi_tbtt_offset_info {
+ u32 vdev_id;
+ u32 tbtt_offset;
+ u32 tbtt_qtime_low_us;
+ u32 tbtt_qtime_high_us;
+} __packed;
+
+struct wmi_tbtt_offset_event {
+ u32 num_vdevs;
+} __packed;
+
+struct wmi_tbtt_offset_ev_arg {
+ u32 vdev_id;
+ u32 tbtt_offset;
+ u32 tbtt_qtime_low_us;
+ u32 tbtt_qtime_high_us;
+} __packed;
+
#define WMI_REG_CLIENT_MAX 4
struct wmi_reg_chan_list_cc_ext_event {
--
2.7.4