If supported, update transmit airtime in mac80211 with the airtime
values reported by the firmware. TX airtime of the PPDU is reported
via HTT data TX completion indication message.
A new service flag 'WMI_SERVICE_REPORT_AIRTIME' is added to advertise
the firmware support. For firmwares which do not support this feature,
TX airtime is calculated in the driver using TX bitrate.
Hardwares tested : QCA9984
Firmwares tested : 10.4-3.6.1-00841
Signed-off-by: Manikanta Pubbisetty <[email protected]>
---
* Changes are made on top of Rajkumar's changes for ATF
drivers/net/wireless/ath/ath10k/core.c | 3 ++
drivers/net/wireless/ath/ath10k/htt.h | 21 ++++++++++++-
drivers/net/wireless/ath/ath10k/htt_rx.c | 52 ++++++++++++++++++++++++++++++--
drivers/net/wireless/ath/ath10k/mac.c | 6 +++-
drivers/net/wireless/ath/ath10k/txrx.c | 2 +-
drivers/net/wireless/ath/ath10k/wmi.h | 42 ++++++++++++++++++++++++++
6 files changed, 121 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index adf2b13..ce2338b 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2599,6 +2599,9 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
ar->wmi.svc_map))
val |= WMI_10_4_TX_DATA_ACK_RSSI;
+ if (test_bit(WMI_SERVICE_REPORT_AIRTIME, ar->wmi.svc_map))
+ val |= WMI_10_4_REPORT_AIRTIME;
+
status = ath10k_mac_ext_resource_config(ar, val);
if (status) {
ath10k_err(ar,
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index a76f7c9..e2d40ab 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -564,6 +564,7 @@ struct htt_mgmt_tx_completion {
#define HTT_RX_INDICATION_INFO0_EXT_TID_LSB (0)
#define HTT_RX_INDICATION_INFO0_FLUSH_VALID (1 << 5)
#define HTT_RX_INDICATION_INFO0_RELEASE_VALID (1 << 6)
+#define HTT_RX_INDICATION_INFO0_PPDU_DURATION BIT(7)
#define HTT_RX_INDICATION_INFO1_FLUSH_START_SEQNO_MASK 0x0000003F
#define HTT_RX_INDICATION_INFO1_FLUSH_START_SEQNO_LSB 0
@@ -576,7 +577,10 @@ struct htt_mgmt_tx_completion {
#define HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES_MASK 0xFF000000
#define HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES_LSB 24
-#define HTT_TX_CMPL_FLAG_DATA_RSSI BIT(0)
+#define HTT_TX_CMPL_FLAG_DATA_RSSI BIT(0)
+#define HTT_TX_CMPL_FLAG_PPID_PRESENT BIT(1)
+#define HTT_TX_CMPL_FLAG_PA_PRESENT BIT(2)
+#define HTT_TX_CMPL_FLAG_PPDU_DURATION_PRESENT BIT(3)
struct htt_rx_indication_hdr {
u8 info0; /* %HTT_RX_INDICATION_INFO0_ */
@@ -866,6 +870,21 @@ struct htt_data_tx_completion {
__le16 msdus[0]; /* variable length based on %num_msdus */
} __packed;
+#define HTT_TX_PPDU_DUR_INFO0_PEER_ID_MASK GENMASK(15, 0)
+#define HTT_TX_PPDU_DUR_INFO0_TID_MASK GENMASK(20, 16)
+
+struct htt_data_tx_ppdu_dur {
+ __le32 info0; /* HTT_TX_PPDU_DUR_INFO0_ */
+ __le32 tx_duration; /* in usecs */
+} __packed;
+
+#define HTT_TX_COMPL_PPDU_DUR_INFO0_NUM_ENTRIES_MASK GENMASK(7, 0)
+
+struct htt_data_tx_compl_ppdu_dur {
+ __le32 info0; /* HTT_TX_COMPL_PPDU_DUR_INFO0_ */
+ struct htt_data_tx_ppdu_dur ppdu_dur[0];
+} __packed;
+
struct htt_tx_compl_ind_base {
u32 hdr;
u16 payload[1/*or more*/];
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 0f775be..3b55f8a 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -2003,8 +2003,12 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
int status = MS(resp->data_tx_completion.flags, HTT_DATA_TX_STATUS);
__le16 msdu_id, *msdus;
bool rssi_enabled = false;
- u8 msdu_count = 0;
+ u8 msdu_count = 0, num_airtime_records, tid;
int i;
+ struct htt_data_tx_compl_ppdu_dur *ppdu_info;
+ struct ath10k_peer *peer;
+ u16 ppdu_info_offset = 0, peer_id;
+ u32 tx_duration;
switch (status) {
case HTT_DATA_TX_STATUS_NO_ACK:
@@ -2028,12 +2032,12 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
resp->data_tx_completion.num_msdus);
msdu_count = resp->data_tx_completion.num_msdus;
+ msdus = resp->data_tx_completion.msdus;
if (resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_DATA_RSSI)
rssi_enabled = true;
for (i = 0; i < msdu_count; i++) {
- msdus = resp->data_tx_completion.msdus;
msdu_id = msdus[i];
tx_done.msdu_id = __le16_to_cpu(msdu_id);
@@ -2065,6 +2069,50 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
ath10k_txrx_tx_unref(htt, &tx_done);
}
}
+
+ if (!(resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_PPDU_DURATION_PRESENT))
+ return;
+
+ ppdu_info_offset = (msdu_count & 0x01) ? msdu_count + 1 : msdu_count;
+
+ if (rssi_enabled)
+ ppdu_info_offset += ppdu_info_offset;
+
+ if (resp->data_tx_completion.flags2 &
+ (HTT_TX_CMPL_FLAG_PPID_PRESENT | HTT_TX_CMPL_FLAG_PA_PRESENT))
+ ppdu_info_offset += 2;
+
+ ppdu_info = (struct htt_data_tx_compl_ppdu_dur *)&msdus[ppdu_info_offset];
+ num_airtime_records = FIELD_GET(HTT_TX_COMPL_PPDU_DUR_INFO0_NUM_ENTRIES_MASK,
+ __le32_to_cpu(ppdu_info->info0));
+
+ for (i = 0; i < num_airtime_records; i++) {
+ struct htt_data_tx_ppdu_dur *ppdu_dur;
+ u32 info0;
+
+ ppdu_dur = &ppdu_info->ppdu_dur[i];
+ info0 = __le32_to_cpu(ppdu_dur->info0);
+
+ peer_id = FIELD_GET(HTT_TX_PPDU_DUR_INFO0_PEER_ID_MASK,
+ info0);
+ rcu_read_lock();
+ spin_lock_bh(&ar->data_lock);
+
+ peer = ath10k_peer_find_by_id(ar, peer_id);
+ if (!peer) {
+ spin_unlock_bh(&ar->data_lock);
+ rcu_read_unlock();
+ continue;
+ }
+
+ tid = FIELD_GET(HTT_TX_PPDU_DUR_INFO0_TID_MASK, info0);
+ tx_duration = __le32_to_cpu(ppdu_dur->tx_duration);
+
+ ieee80211_sta_register_airtime(peer->sta, tid, tx_duration, 0);
+
+ spin_unlock_bh(&ar->data_lock);
+ rcu_read_unlock();
+ }
}
static void ath10k_htt_rx_addba(struct ath10k *ar, struct htt_resp *resp)
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 428730f..7694abb 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3967,6 +3967,9 @@ static u16 ath10k_mac_update_airtime(struct ath10k *ar,
if (!txq || !txq->sta)
return airtime;
+ if (test_bit(WMI_SERVICE_REPORT_AIRTIME, ar->wmi.svc_map))
+ return airtime;
+
spin_lock_bh(&ar->data_lock);
arsta = (struct ath10k_sta *)txq->sta->drv_priv;
@@ -8615,7 +8618,8 @@ int ath10k_mac_register(struct ath10k *ar)
wiphy_ext_feature_set(ar->hw->wiphy,
NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
- if (ath10k_peer_stats_enabled(ar))
+ if (ath10k_peer_stats_enabled(ar) ||
+ test_bit(WMI_SERVICE_REPORT_AIRTIME, ar->wmi.svc_map))
wiphy_ext_feature_set(ar->hw->wiphy,
NL80211_EXT_FEATURE_AIRTIME_FAIRNESS);
/*
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c
index 8e7c416..134e1c5 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -95,7 +95,7 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
wake_up(&htt->empty_tx_wq);
spin_unlock_bh(&htt->tx_lock);
- if (txq && txq->sta)
+ if (txq && txq->sta && skb_cb->airtime_est)
ieee80211_sta_register_airtime(txq->sta, txq->tid,
skb_cb->airtime_est, 0);
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 58e33ab..f41d654 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -205,6 +205,14 @@ enum wmi_service {
WMI_SERVICE_SPOOF_MAC_SUPPORT,
WMI_SERVICE_TX_DATA_ACK_RSSI,
WMI_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT,
+ WMI_SERVICE_HTT_ASSERT_TRIGGER_SUPPORT,
+ WMI_SERVICE_VDEV_FILTER_NEIGHBOR_RX_PACKETS,
+ WMI_SERVICE_VDEV_DISABLE_4_ADDR_SRC_LRN_SUPPORT,
+ WMI_SERVICE_PEER_CHWIDTH_CHANGE,
+ WMI_SERVICE_RX_FILTER_OUT_COUNT,
+ WMI_SERVICE_RTT_RESPONDER_ROLE,
+ WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,
+ WMI_SERVICE_REPORT_AIRTIME,
/* keep last */
WMI_SERVICE_MAX,
@@ -359,6 +367,14 @@ enum wmi_10_4_service {
WMI_10_4_SERVICE_PEER_TID_CONFIGS_SUPPORT,
WMI_10_4_SERVICE_VDEV_BCN_RATE_CONTROL,
WMI_10_4_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT,
+ WMI_10_4_SERVICE_HTT_ASSERT_TRIGGER_SUPPORT,
+ WMI_10_4_SERVICE_VDEV_FILTER_NEIGHBOR_RX_PACKETS,
+ WMI_10_4_SERVICE_VDEV_DISABLE_4_ADDR_SRC_LRN_SUPPORT,
+ WMI_10_4_SERVICE_PEER_CHWIDTH_CHANGE,
+ WMI_10_4_SERVICE_RX_FILTER_OUT_COUNT,
+ WMI_10_4_SERVICE_RTT_RESPONDER_ROLE,
+ WMI_10_4_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,
+ WMI_10_4_SERVICE_REPORT_AIRTIME,
};
static inline char *wmi_service_name(int service_id)
@@ -474,6 +490,14 @@ static inline char *wmi_service_name(int service_id)
SVCSTR(WMI_SERVICE_RESET_CHIP);
SVCSTR(WMI_SERVICE_TX_DATA_ACK_RSSI);
SVCSTR(WMI_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT);
+ SVCSTR(WMI_SERVICE_HTT_ASSERT_TRIGGER_SUPPORT);
+ SVCSTR(WMI_SERVICE_VDEV_FILTER_NEIGHBOR_RX_PACKETS);
+ SVCSTR(WMI_SERVICE_VDEV_DISABLE_4_ADDR_SRC_LRN_SUPPORT);
+ SVCSTR(WMI_SERVICE_PEER_CHWIDTH_CHANGE);
+ SVCSTR(WMI_SERVICE_RX_FILTER_OUT_COUNT);
+ SVCSTR(WMI_SERVICE_RTT_RESPONDER_ROLE);
+ SVCSTR(WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT);
+ SVCSTR(WMI_SERVICE_REPORT_AIRTIME);
default:
return NULL;
}
@@ -786,6 +810,22 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out,
WMI_SERVICE_TX_DATA_ACK_RSSI, len);
SVCMAP(WMI_10_4_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT,
WMI_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT, len);
+ SVCMAP(WMI_10_4_SERVICE_HTT_ASSERT_TRIGGER_SUPPORT,
+ WMI_SERVICE_HTT_ASSERT_TRIGGER_SUPPORT, len);
+ SVCMAP(WMI_10_4_SERVICE_VDEV_FILTER_NEIGHBOR_RX_PACKETS,
+ WMI_SERVICE_VDEV_FILTER_NEIGHBOR_RX_PACKETS, len);
+ SVCMAP(WMI_10_4_SERVICE_VDEV_DISABLE_4_ADDR_SRC_LRN_SUPPORT,
+ WMI_SERVICE_VDEV_DISABLE_4_ADDR_SRC_LRN_SUPPORT, len);
+ SVCMAP(WMI_10_4_SERVICE_PEER_CHWIDTH_CHANGE,
+ WMI_SERVICE_PEER_CHWIDTH_CHANGE, len);
+ SVCMAP(WMI_10_4_SERVICE_RX_FILTER_OUT_COUNT,
+ WMI_SERVICE_RX_FILTER_OUT_COUNT, len);
+ SVCMAP(WMI_10_4_SERVICE_RTT_RESPONDER_ROLE,
+ WMI_SERVICE_RTT_RESPONDER_ROLE, len);
+ SVCMAP(WMI_10_4_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,
+ WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT, len);
+ SVCMAP(WMI_10_4_SERVICE_REPORT_AIRTIME,
+ WMI_SERVICE_REPORT_AIRTIME, len);
}
#undef SVCMAP
@@ -2956,6 +2996,8 @@ enum wmi_10_4_feature_mask {
WMI_10_4_TDLS_CONN_TRACKER_IN_HOST_MODE = BIT(11),
WMI_10_4_TDLS_EXPLICIT_MODE_ONLY = BIT(12),
WMI_10_4_TX_DATA_ACK_RSSI = BIT(16),
+ WMI_10_4_EXT_PEER_TID_CONFIGS_SUPPORT = BIT(17),
+ WMI_10_4_REPORT_AIRTIME = BIT(18),
};
--
2.7.4
Manikanta Pubbisetty <[email protected]> wrote:
> If supported, update transmit airtime in mac80211 with the airtime
> values reported by the firmware. TX airtime of the PPDU is reported
> via HTT data TX completion indication message.
>
> A new service flag 'WMI_SERVICE_REPORT_AIRTIME' is added to advertise
> the firmware support. For firmwares which do not support this feature,
> TX airtime is calculated in the driver using TX bitrate.
>
> Hardwares tested : QCA9984
> Firmwares tested : 10.4-3.6.1-00841
>
> Signed-off-by: Manikanta Pubbisetty <[email protected]>
> Signed-off-by: Kalle Valo <[email protected]>
I had some conflicts, please carefully check my resolution in the pending branch:
https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git/commit/?h=pending&id=1baca5592c99c9d61924956c56c620d371b61d96
$ git am -s --reject 10684687.mbox
Applying: ath10k: report tx airtime provided by fw
Checking patch drivers/net/wireless/ath/ath10k/core.c...
Hunk #1 succeeded at 2631 (offset 32 lines).
Checking patch drivers/net/wireless/ath/ath10k/htt.h...
Hunk #1 succeeded at 571 (offset 7 lines).
Hunk #2 succeeded at 584 (offset 7 lines).
Hunk #3 succeeded at 877 (offset 7 lines).
Checking patch drivers/net/wireless/ath/ath10k/htt_rx.c...
Hunk #1 succeeded at 2220 (offset 217 lines).
Hunk #2 succeeded at 2249 (offset 217 lines).
Hunk #3 succeeded at 2286 (offset 217 lines).
Checking patch drivers/net/wireless/ath/ath10k/mac.c...
Hunk #1 succeeded at 4007 (offset 40 lines).
error: while searching for:
wiphy_ext_feature_set(ar->hw->wiphy,
NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
if (ath10k_peer_stats_enabled(ar))
wiphy_ext_feature_set(ar->hw->wiphy,
NL80211_EXT_FEATURE_AIRTIME_FAIRNESS);
/*
error: patch failed: drivers/net/wireless/ath/ath10k/mac.c:8615
Checking patch drivers/net/wireless/ath/ath10k/txrx.c...
Checking patch drivers/net/wireless/ath/ath10k/wmi.h...
error: while searching for:
WMI_SERVICE_SPOOF_MAC_SUPPORT,
WMI_SERVICE_TX_DATA_ACK_RSSI,
WMI_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT,
/* keep last */
WMI_SERVICE_MAX,
error: patch failed: drivers/net/wireless/ath/ath10k/wmi.h:205
error: while searching for:
WMI_10_4_SERVICE_PEER_TID_CONFIGS_SUPPORT,
WMI_10_4_SERVICE_VDEV_BCN_RATE_CONTROL,
WMI_10_4_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT,
};
static inline char *wmi_service_name(int service_id)
error: patch failed: drivers/net/wireless/ath/ath10k/wmi.h:359
error: while searching for:
SVCSTR(WMI_SERVICE_RESET_CHIP);
SVCSTR(WMI_SERVICE_TX_DATA_ACK_RSSI);
SVCSTR(WMI_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT);
default:
return NULL;
}
error: patch failed: drivers/net/wireless/ath/ath10k/wmi.h:474
error: while searching for:
WMI_SERVICE_TX_DATA_ACK_RSSI, len);
SVCMAP(WMI_10_4_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT,
WMI_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT, len);
}
#undef SVCMAP
error: patch failed: drivers/net/wireless/ath/ath10k/wmi.h:786
Hunk #5 succeeded at 2989 (offset -7 lines).
Applied patch drivers/net/wireless/ath/ath10k/core.c cleanly.
Applied patch drivers/net/wireless/ath/ath10k/htt.h cleanly.
Applied patch drivers/net/wireless/ath/ath10k/htt_rx.c cleanly.
Applying patch drivers/net/wireless/ath/ath10k/mac.c with 1 reject...
Hunk #1 applied cleanly.
Rejected hunk #2.
Applied patch drivers/net/wireless/ath/ath10k/txrx.c cleanly.
Applying patch drivers/net/wireless/ath/ath10k/wmi.h with 4 rejects...
Rejected hunk #1.
Rejected hunk #2.
Rejected hunk #3.
Rejected hunk #4.
Hunk #5 applied cleanly.
Patch failed at 0001 ath10k: report tx airtime provided by fw
--
https://patchwork.kernel.org/patch/10684687/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
Manikanta Pubbisetty <[email protected]> wrote:
> If supported, update transmit airtime in mac80211 with the airtime
> values reported by the firmware. TX airtime of the PPDU is reported
> via HTT data TX completion indication message.
>
> A new service flag 'WMI_SERVICE_REPORT_AIRTIME' is added to advertise
> the firmware support. For firmwares which do not support this feature,
> TX airtime is calculated in the driver using TX bitrate.
>
> Hardwares tested : QCA9984
> Firmwares tested : 10.4-3.6.1-00841
>
> Signed-off-by: Manikanta Pubbisetty <[email protected]>
> Signed-off-by: Kalle Valo <[email protected]>
Patch applied to ath-next branch of ath.git, thanks.
bb31b7cb106c ath10k: report tx airtime provided by fw
--
https://patchwork.kernel.org/patch/10684687/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches