mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-18 18:01:23 +00:00
This series is based on * 2020-07-10 ipq6018-ilq-11-0_qca_oem-034672b0676c37b1f4519e5720e18e95fe6236ef Add support for * qsdk kernel/v4.4 * qsdk ethernet subsystem * v5.7 ath11k backport + QualComm staging patches (wlan_ap_1.0) * ath11k-firmware * hostapd/iw/... Feature support * full boot, system detection * sysupgrade to nand * HE support via latest hostapd * driver support for usb, crypto, hwmon, cpufreq, ... Missing * NSS/HW flow offloading - FW blob is not redistributable Using the qsdk v4.4 is an intermediate solution while the vanilla is being tested. Vanilla kernel is almost on feature par. Work has already started to upstream the ethernet and switch drivers. Once complete the target will be fully upstream. Signed-off-by: John Crispin <john@phrozen.org>
278 lines
8.7 KiB
Diff
278 lines
8.7 KiB
Diff
--- a/drivers/net/wireless/ath/ath11k/core.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
|
@@ -197,6 +197,16 @@ enum ath11k_dev_flags {
|
|
ATH11K_FLAG_FW_RESTART_FOR_HOST,
|
|
};
|
|
|
|
+#define ATH11K_STATS_MGMT_FRM_TYPE_MAX 16
|
|
+
|
|
+struct ath11k_mgmt_frame_stats {
|
|
+ u32 tx_succ_cnt[ATH11K_STATS_MGMT_FRM_TYPE_MAX];
|
|
+ u32 tx_fail_cnt[ATH11K_STATS_MGMT_FRM_TYPE_MAX];
|
|
+ u32 rx_cnt[ATH11K_STATS_MGMT_FRM_TYPE_MAX];
|
|
+ u32 tx_compl_succ[ATH11K_STATS_MGMT_FRM_TYPE_MAX];
|
|
+ u32 tx_compl_fail[ATH11K_STATS_MGMT_FRM_TYPE_MAX];
|
|
+};
|
|
+
|
|
struct ath11k_vif {
|
|
u32 vdev_id;
|
|
enum wmi_vdev_type vdev_type;
|
|
@@ -241,6 +251,7 @@ struct ath11k_vif {
|
|
int rtscts_prot_mode;
|
|
int txpower;
|
|
struct dentry *debugfs_twt;
|
|
+ struct ath11k_mgmt_frame_stats mgmt_stats;
|
|
};
|
|
|
|
struct ath11k_vif_iter {
|
|
--- a/drivers/net/wireless/ath/ath11k/debug.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/debug.c
|
|
@@ -1626,6 +1626,87 @@ static const struct file_operations fops
|
|
.open = simple_open
|
|
};
|
|
|
|
+static ssize_t ath11k_dump_mgmt_stats(struct file *file, char __user *ubuf,
|
|
+ size_t count, loff_t *ppos)
|
|
+{
|
|
+ struct ath11k *ar = file->private_data;
|
|
+ struct ath11k_vif *arvif = NULL;
|
|
+ struct ath11k_mgmt_frame_stats *mgmt_stats;
|
|
+ int len = 0, ret, i;
|
|
+ int size = (TARGET_NUM_VDEVS - 1) * 1500;
|
|
+ char *buf;
|
|
+ const char *mgmt_frm_type[ATH11K_STATS_MGMT_FRM_TYPE_MAX-1] = {"assoc_req", "assoc_resp",
|
|
+ "reassoc_req", "reassoc_resp",
|
|
+ "probe_req", "probe_resp",
|
|
+ "timing_advertisement", "reserved",
|
|
+ "beacon", "atim", "disassoc",
|
|
+ "auth", "deauth", "action", "action_no_ack"};
|
|
+
|
|
+ if (ar->state != ATH11K_STATE_ON)
|
|
+ return -ENETDOWN;
|
|
+
|
|
+ buf = kzalloc(size, GFP_KERNEL);
|
|
+ if (!buf)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ mutex_lock(&ar->conf_mutex);
|
|
+ spin_lock_bh(&ar->data_lock);
|
|
+
|
|
+ list_for_each_entry (arvif, &ar->arvifs, list) {
|
|
+ if (!arvif)
|
|
+ break;
|
|
+
|
|
+ if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
|
|
+ continue;
|
|
+
|
|
+ mgmt_stats = &arvif->mgmt_stats;
|
|
+ len += scnprintf(buf + len, size - len, "MGMT frame stats for vdev %u :\n",
|
|
+ arvif->vdev_id);
|
|
+ len += scnprintf(buf + len, size - len, " TX stats :\n ");
|
|
+ len += scnprintf(buf + len, size - len, " Success frames:\n");
|
|
+ for (i = 0; i < ATH11K_STATS_MGMT_FRM_TYPE_MAX-1; i++)
|
|
+ len += scnprintf(buf + len, size - len, " %s: %d\n", mgmt_frm_type[i],
|
|
+ mgmt_stats->tx_succ_cnt[i]);
|
|
+
|
|
+ len += scnprintf(buf + len, size - len, " Failed frames:\n");
|
|
+
|
|
+ for (i = 0; i < ATH11K_STATS_MGMT_FRM_TYPE_MAX-1; i++)
|
|
+ len += scnprintf(buf + len, size - len, " %s: %d\n", mgmt_frm_type[i],
|
|
+ mgmt_stats->tx_fail_cnt[i]);
|
|
+
|
|
+ len += scnprintf(buf + len, size - len, " RX stats :\n");
|
|
+ len += scnprintf(buf + len, size - len, " Success frames:\n");
|
|
+ for (i = 0; i < ATH11K_STATS_MGMT_FRM_TYPE_MAX-1; i++)
|
|
+ len += scnprintf(buf + len, size - len, " %s: %d\n", mgmt_frm_type[i],
|
|
+ mgmt_stats->rx_cnt[i]);
|
|
+
|
|
+ len += scnprintf(buf + len, size - len, " Tx completion stats :\n");
|
|
+ len += scnprintf(buf + len, size - len, " success completions:\n");
|
|
+ for (i = 0; i < ATH11K_STATS_MGMT_FRM_TYPE_MAX-1; i++)
|
|
+ len += scnprintf(buf + len, size - len, " %s: %d\n", mgmt_frm_type[i],
|
|
+ mgmt_stats->tx_compl_succ[i]);
|
|
+ len += scnprintf(buf + len, size - len, " failure completions:\n");
|
|
+ for (i = 0; i < ATH11K_STATS_MGMT_FRM_TYPE_MAX-1; i++)
|
|
+ len += scnprintf(buf + len, size - len, " %s: %d\n", mgmt_frm_type[i],
|
|
+ mgmt_stats->tx_compl_fail[i]);
|
|
+ }
|
|
+
|
|
+ spin_unlock_bh(&ar->data_lock);
|
|
+
|
|
+ if (len > size)
|
|
+ len = size;
|
|
+
|
|
+ ret = simple_read_from_buffer(ubuf, count, ppos, buf, len);
|
|
+ mutex_unlock(&ar->conf_mutex);
|
|
+ kfree(buf);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static const struct file_operations fops_dump_mgmt_stats = {
|
|
+ .read = ath11k_dump_mgmt_stats,
|
|
+ .open = simple_open
|
|
+};
|
|
+
|
|
int ath11k_debug_register(struct ath11k *ar)
|
|
{
|
|
struct ath11k_base *ab = ar->ab;
|
|
@@ -1670,6 +1751,8 @@ int ath11k_debug_register(struct ath11k
|
|
debugfs_create_file("btcoex_duty_cycle", 0644,
|
|
ar->debug.debugfs_pdev, ar,
|
|
&fops__btcoex_duty_cycle);
|
|
+ debugfs_create_file("dump_mgmt_stats", 0644, ar->debug.debugfs_pdev,
|
|
+ ar, &fops_dump_mgmt_stats);
|
|
|
|
if (ar->hw->wiphy->bands[NL80211_BAND_5GHZ]) {
|
|
debugfs_create_file("dfs_simulate_radar", 0200,
|
|
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
|
@@ -4679,21 +4679,36 @@ static void ath11k_mac_op_tx(struct ieee
|
|
struct ieee80211_vif *vif = info->control.vif;
|
|
struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
|
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
|
+ struct ath11k_mgmt_frame_stats *mgmt_stats = &arvif->mgmt_stats;
|
|
bool is_prb_rsp;
|
|
int ret;
|
|
+ u16 frm_type = 0;
|
|
|
|
skb_cb->flags = 0;
|
|
if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) {
|
|
skb_cb->flags = ATH11K_SKB_HW_80211_ENCAP;
|
|
} 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);
|
|
ret = ath11k_mac_mgmt_tx(ar, skb, is_prb_rsp);
|
|
if (ret) {
|
|
- if (ret != -EBUSY) {
|
|
+ if (ret != -EBUSY)
|
|
ath11k_warn(ar->ab, "failed to queue management frame %d\n",
|
|
ret);
|
|
- }
|
|
ieee80211_free_txskb(ar->hw, skb);
|
|
+ spin_lock_bh(&ar->data_lock);
|
|
+
|
|
+ mgmt_stats->tx_fail_cnt[frm_type]++;
|
|
+
|
|
+ spin_unlock_bh(&ar->data_lock);
|
|
+
|
|
+ } else {
|
|
+
|
|
+ spin_lock_bh(&ar->data_lock);
|
|
+
|
|
+ mgmt_stats->tx_succ_cnt[frm_type]++;
|
|
+
|
|
+ spin_unlock_bh(&ar->data_lock);
|
|
}
|
|
return;
|
|
}
|
|
--- a/drivers/net/wireless/ath/ath11k/peer.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/peer.c
|
|
@@ -335,6 +335,7 @@ int ath11k_peer_create(struct ath11k *ar
|
|
|
|
peer->sec_type = HAL_ENCRYPT_TYPE_OPEN;
|
|
peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN;
|
|
+ peer->vif = arvif->vif;
|
|
|
|
ar->num_peers++;
|
|
|
|
--- a/drivers/net/wireless/ath/ath11k/peer.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/peer.h
|
|
@@ -20,6 +20,7 @@ struct ppdu_user_delayba {
|
|
struct ath11k_peer {
|
|
struct list_head list;
|
|
struct ieee80211_sta *sta;
|
|
+ struct ieee80211_vif *vif;
|
|
int vdev_id;
|
|
u8 addr[ETH_ALEN];
|
|
int peer_id;
|
|
--- a/drivers/net/wireless/ath/ath11k/wmi.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
|
|
@@ -4705,6 +4705,12 @@ static int wmi_process_mgmt_tx_comp(stru
|
|
struct sk_buff *msdu;
|
|
struct ieee80211_tx_info *info;
|
|
struct ath11k_skb_cb *skb_cb;
|
|
+ struct ieee80211_hdr *hdr;
|
|
+ struct ath11k_peer *peer;
|
|
+ struct ieee80211_vif *vif;
|
|
+ struct ath11k_vif *arvif;
|
|
+ struct ath11k_mgmt_frame_stats *mgmt_stats;
|
|
+ u16 frm_type;
|
|
|
|
spin_lock_bh(&ar->txmgmt_idr_lock);
|
|
msdu = idr_find(&ar->txmgmt_idr, desc_id);
|
|
@@ -4726,6 +4732,31 @@ static int wmi_process_mgmt_tx_comp(stru
|
|
if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && !status)
|
|
info->flags |= IEEE80211_TX_STAT_ACK;
|
|
|
|
+ hdr = (struct ieee80211_hdr *)msdu->data;
|
|
+ frm_type = FIELD_GET(IEEE80211_FCTL_STYPE, hdr->frame_control);
|
|
+
|
|
+ spin_lock_bh(&ar->ab->base_lock);
|
|
+ peer = ath11k_peer_find_by_addr(ar->ab, hdr->addr2);
|
|
+ if (!peer) {
|
|
+ spin_unlock_bh(&ar->ab->base_lock);
|
|
+ ath11k_warn(ar->ab, "failed to find peer to update txcompl mgmt stats\n");
|
|
+ goto skip_mgmt_stats;
|
|
+ }
|
|
+
|
|
+ vif = peer->vif;
|
|
+ spin_unlock_bh(&ar->ab->base_lock);
|
|
+
|
|
+ spin_lock_bh(&ar->data_lock);
|
|
+ arvif = ath11k_vif_to_arvif(vif);
|
|
+ mgmt_stats = &arvif->mgmt_stats;
|
|
+
|
|
+ if (!status)
|
|
+ mgmt_stats->tx_compl_succ[frm_type]++;
|
|
+ else
|
|
+ mgmt_stats->tx_compl_fail[frm_type]++;
|
|
+ spin_unlock_bh(&ar->data_lock);
|
|
+
|
|
+skip_mgmt_stats:
|
|
ieee80211_tx_status_irqsafe(ar->hw, msdu);
|
|
|
|
/* WARN when we received this event without doing any mgmt tx */
|
|
@@ -6049,6 +6080,11 @@ static void ath11k_mgmt_rx_event(struct
|
|
struct ieee80211_hdr *hdr;
|
|
u16 fc;
|
|
struct ieee80211_supported_band *sband;
|
|
+ struct ath11k_peer *peer;
|
|
+ struct ieee80211_vif *vif;
|
|
+ struct ath11k_vif *arvif;
|
|
+ struct ath11k_mgmt_frame_stats *mgmt_stats;
|
|
+ u16 frm_type = 0;
|
|
|
|
if (ath11k_pull_mgmt_rx_params_tlv(ab, skb, &rx_ev) != 0) {
|
|
ath11k_warn(ab, "failed to extract mgmt rx event");
|
|
@@ -6107,7 +6143,30 @@ static void ath11k_mgmt_rx_event(struct
|
|
|
|
hdr = (struct ieee80211_hdr *)skb->data;
|
|
fc = le16_to_cpu(hdr->frame_control);
|
|
+ frm_type = FIELD_GET(IEEE80211_FCTL_STYPE, fc);
|
|
+
|
|
+ spin_lock_bh(&ab->base_lock);
|
|
+
|
|
+ peer = ath11k_peer_find_by_addr(ab, hdr->addr1);
|
|
+ if(!peer)
|
|
+ peer = ath11k_peer_find_by_addr(ab, hdr->addr3);
|
|
+ if (!peer) {
|
|
+ spin_unlock_bh(&ab->base_lock);
|
|
+ goto skip_mgmt_stats;
|
|
+ }
|
|
+
|
|
+ vif = peer->vif;
|
|
+
|
|
+ spin_unlock_bh(&ab->base_lock);
|
|
+ spin_lock_bh(&ar->data_lock);
|
|
+
|
|
+ arvif = ath11k_vif_to_arvif(vif);
|
|
+ mgmt_stats = &arvif->mgmt_stats;
|
|
+ mgmt_stats->rx_cnt[frm_type]++;
|
|
+
|
|
+ spin_unlock_bh(&ar->data_lock);
|
|
|
|
+skip_mgmt_stats:
|
|
/* Firmware is guaranteed to report all essential management frames via
|
|
* WMI while it can deliver some extra via HTT. Since there can be
|
|
* duplicates split the reporting wrt monitor/sniffing.
|