2015-01-30 09:48:20

by Michal Kazior

[permalink] [raw]
Subject: [PATCH 0/4] ath10k: implement fw stats for wmi-tlv

There are some slight differences in fw stats
(sic) in wmi-tlv.

Firmware has changed the querying scheme and no
longer requires the ping-pong to get all stats.
The patchset doesn't change this behaviour so with
wmi-tlv it's possible to see the following
warnings when reading fw stats:

ath10k_pci 0000:00:06.0: received unsolicited stats update event

The logic in ath10k still produces correct results
so this is harmless.

I wonder how to deal with this in a sane way. An
`if (op_ver == WMI_TLV)` is a little bad but
having a new ar->fw_feature flag just for a debug
facility like this is a bit silly. Or we can just
drop the warning and leave a comment. Ideas?


Michal Kazior (4):
ath10k: add vdev stats processing
ath10k: change request stats command prototype
ath10k: add more wmi fw stat defines
ath10k: implement fw stats for wmi-tlv

drivers/net/wireless/ath/ath10k/core.h | 20 +++++
drivers/net/wireless/ath/ath10k/debug.c | 101 +++++++++++++++++++++++++-
drivers/net/wireless/ath/ath10k/wmi-ops.h | 7 +-
drivers/net/wireless/ath/ath10k/wmi-tlv.c | 117 ++++++++++++++++++++++++++++--
drivers/net/wireless/ath/ath10k/wmi-tlv.h | 9 +++
drivers/net/wireless/ath/ath10k/wmi.c | 7 +-
drivers/net/wireless/ath/ath10k/wmi.h | 10 ++-
7 files changed, 254 insertions(+), 17 deletions(-)

--
1.8.5.3



2015-01-30 09:48:27

by Michal Kazior

[permalink] [raw]
Subject: [PATCH 3/4] ath10k: add more wmi fw stat defines

New qca6174 wmi-tlv firmware revisions support
more stat event bits.

Signed-off-by: Michal Kazior <[email protected]>
---
drivers/net/wireless/ath/ath10k/debug.c | 2 +-
drivers/net/wireless/ath/ath10k/wmi.h | 10 +++++++---
2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index f0a6b93..33f36ee 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -395,7 +395,7 @@ static int ath10k_debug_fw_stats_request(struct ath10k *ar)

reinit_completion(&ar->debug.fw_stats_complete);

- ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT);
+ ret = ath10k_wmi_request_stats(ar, WMI_STAT_PEER);
if (ret) {
ath10k_warn(ar, "could not request stats (%d)\n", ret);
return ret;
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 20ce360..0eb0959 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -3057,8 +3057,12 @@ struct wmi_pdev_stats_peer {
} __packed;

enum wmi_stats_id {
- WMI_REQUEST_PEER_STAT = 0x01,
- WMI_REQUEST_AP_STAT = 0x02
+ WMI_STAT_PEER = BIT(0),
+ WMI_STAT_AP = BIT(1),
+ WMI_STAT_PDEV = BIT(2),
+ WMI_STAT_VDEV = BIT(3),
+ WMI_STAT_BCNFLT = BIT(4),
+ WMI_STAT_VDEV_RATE = BIT(5),
};

struct wlan_inst_rssi_args {
@@ -3093,7 +3097,7 @@ struct wmi_pdev_suspend_cmd {
} __packed;

struct wmi_stats_event {
- __le32 stats_id; /* %WMI_REQUEST_ */
+ __le32 stats_id; /* WMI_STAT_ */
/*
* number of pdev stats event structures
* (wmi_pdev_stats) 0 or 1
--
1.8.5.3


2015-01-30 09:48:22

by Michal Kazior

[permalink] [raw]
Subject: [PATCH 2/4] ath10k: change request stats command prototype

The expected parameter is not a single value but a
mask of values.

Signed-off-by: Michal Kazior <[email protected]>
---
drivers/net/wireless/ath/ath10k/wmi-ops.h | 7 +++----
drivers/net/wireless/ath/ath10k/wmi-tlv.c | 5 ++---
drivers/net/wireless/ath/ath10k/wmi.c | 7 ++++---
3 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h
index 058f88b..ec8e156 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
@@ -107,8 +107,7 @@ struct wmi_ops {
struct sk_buff *(*gen_beacon_dma)(struct ath10k_vif *arvif);
struct sk_buff *(*gen_pdev_set_wmm)(struct ath10k *ar,
const struct wmi_wmm_params_all_arg *arg);
- struct sk_buff *(*gen_request_stats)(struct ath10k *ar,
- enum wmi_stats_id stats_id);
+ struct sk_buff *(*gen_request_stats)(struct ath10k *ar, u32 stats_mask);
struct sk_buff *(*gen_force_fw_hang)(struct ath10k *ar,
enum wmi_force_fw_hang_type type,
u32 delay_ms);
@@ -809,14 +808,14 @@ ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar,
}

static inline int
-ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id)
+ath10k_wmi_request_stats(struct ath10k *ar, u32 stats_mask)
{
struct sk_buff *skb;

if (!ar->wmi.ops->gen_request_stats)
return -EOPNOTSUPP;

- skb = ar->wmi.ops->gen_request_stats(ar, stats_id);
+ skb = ar->wmi.ops->gen_request_stats(ar, stats_mask);
if (IS_ERR(skb))
return PTR_ERR(skb);

diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index be32db9..8264f2e 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -2078,8 +2078,7 @@ ath10k_wmi_tlv_op_gen_pdev_set_wmm(struct ath10k *ar,
}

static struct sk_buff *
-ath10k_wmi_tlv_op_gen_request_stats(struct ath10k *ar,
- enum wmi_stats_id stats_id)
+ath10k_wmi_tlv_op_gen_request_stats(struct ath10k *ar, u32 stats_mask)
{
struct wmi_request_stats_cmd *cmd;
struct wmi_tlv *tlv;
@@ -2093,7 +2092,7 @@ ath10k_wmi_tlv_op_gen_request_stats(struct ath10k *ar,
tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_REQUEST_STATS_CMD);
tlv->len = __cpu_to_le16(sizeof(*cmd));
cmd = (void *)tlv->value;
- cmd->stats_id = __cpu_to_le32(stats_id);
+ cmd->stats_id = __cpu_to_le32(stats_mask);

ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv request stats\n");
return skb;
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index ce6f0c7..27e0c18 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -4923,7 +4923,7 @@ ath10k_wmi_op_gen_pdev_set_wmm(struct ath10k *ar,
}

static struct sk_buff *
-ath10k_wmi_op_gen_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id)
+ath10k_wmi_op_gen_request_stats(struct ath10k *ar, u32 stats_mask)
{
struct wmi_request_stats_cmd *cmd;
struct sk_buff *skb;
@@ -4933,9 +4933,10 @@ ath10k_wmi_op_gen_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id)
return ERR_PTR(-ENOMEM);

cmd = (struct wmi_request_stats_cmd *)skb->data;
- cmd->stats_id = __cpu_to_le32(stats_id);
+ cmd->stats_id = __cpu_to_le32(stats_mask);

- ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi request stats %d\n", (int)stats_id);
+ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi request stats 0x%08x\n",
+ stats_mask);
return skb;
}

--
1.8.5.3


2015-01-30 09:48:27

by Michal Kazior

[permalink] [raw]
Subject: [PATCH 4/4] ath10k: implement fw stats for wmi-tlv

This processes and pushes fw stats to the debug
module (if enabled).

Changing the generic ath10k_wmi_requests_stats()
call to use more stat bits has no effect on older
firmware binaries.

Signed-off-by: Michal Kazior <[email protected]>
---
drivers/net/wireless/ath/ath10k/debug.c | 5 +-
drivers/net/wireless/ath/ath10k/wmi-tlv.c | 112 +++++++++++++++++++++++++++++-
drivers/net/wireless/ath/ath10k/wmi-tlv.h | 9 +++
3 files changed, 122 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 33f36ee..518d21c 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -395,7 +395,10 @@ static int ath10k_debug_fw_stats_request(struct ath10k *ar)

reinit_completion(&ar->debug.fw_stats_complete);

- ret = ath10k_wmi_request_stats(ar, WMI_STAT_PEER);
+ ret = ath10k_wmi_request_stats(ar,
+ WMI_STAT_PDEV |
+ WMI_STAT_VDEV |
+ WMI_STAT_PEER);
if (ret) {
ath10k_warn(ar, "could not request stats (%d)\n", ret);
return ret;
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index 8264f2e..737f747 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -869,16 +869,57 @@ static int ath10k_wmi_tlv_op_pull_rdy_ev(struct ath10k *ar,
return 0;
}

+static void ath10k_wmi_tlv_pull_vdev_stats(const struct wmi_tlv_vdev_stats *src,
+ struct ath10k_fw_stats_vdev *dst)
+{
+ int i;
+
+ dst->vdev_id = __le32_to_cpu(src->vdev_id);
+ dst->beacon_snr = __le32_to_cpu(src->beacon_snr);
+ dst->data_snr = __le32_to_cpu(src->data_snr);
+ dst->num_rx_frames = __le32_to_cpu(src->num_rx_frames);
+ dst->num_rts_fail = __le32_to_cpu(src->num_rts_fail);
+ dst->num_rts_success = __le32_to_cpu(src->num_rts_success);
+ dst->num_rx_err = __le32_to_cpu(src->num_rx_err);
+ dst->num_rx_discard = __le32_to_cpu(src->num_rx_discard);
+ dst->num_tx_not_acked = __le32_to_cpu(src->num_tx_not_acked);
+
+ for (i = 0; i < ARRAY_SIZE(src->num_tx_frames); i++)
+ dst->num_tx_frames[i] =
+ __le32_to_cpu(src->num_tx_frames[i]);
+
+ for (i = 0; i < ARRAY_SIZE(src->num_tx_frames_retries); i++)
+ dst->num_tx_frames_retries[i] =
+ __le32_to_cpu(src->num_tx_frames_retries[i]);
+
+ for (i = 0; i < ARRAY_SIZE(src->num_tx_frames_failures); i++)
+ dst->num_tx_frames_failures[i] =
+ __le32_to_cpu(src->num_tx_frames_failures[i]);
+
+ for (i = 0; i < ARRAY_SIZE(src->tx_rate_history); i++)
+ dst->tx_rate_history[i] =
+ __le32_to_cpu(src->tx_rate_history[i]);
+
+ for (i = 0; i < ARRAY_SIZE(src->beacon_rssi_history); i++)
+ dst->beacon_rssi_history[i] =
+ __le32_to_cpu(src->beacon_rssi_history[i]);
+}
+
static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
struct sk_buff *skb,
struct ath10k_fw_stats *stats)
{
const void **tb;
- const struct wmi_stats_event *ev;
+ const struct wmi_tlv_stats_ev *ev;
const void *data;
- u32 num_pdev_stats, num_vdev_stats, num_peer_stats;
+ u32 num_pdev_stats;
+ u32 num_vdev_stats;
+ u32 num_peer_stats;
+ u32 num_bcnflt_stats;
+ u32 num_chan_stats;
size_t data_len;
int ret;
+ int i;

tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
if (IS_ERR(tb)) {
@@ -899,8 +940,73 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
+ num_bcnflt_stats = __le32_to_cpu(ev->num_bcnflt_stats);
+ num_chan_stats = __le32_to_cpu(ev->num_chan_stats);

- WARN_ON(1); /* FIXME: not implemented yet */
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
+ "wmi tlv stats update pdev %i vdev %i peer %i bcnflt %i chan %i\n",
+ num_pdev_stats, num_vdev_stats, num_peer_stats,
+ num_bcnflt_stats, num_chan_stats);
+
+ for (i = 0; i < num_pdev_stats; i++) {
+ const struct wmi_pdev_stats *src;
+ struct ath10k_fw_stats_pdev *dst;
+
+ src = data;
+ if (data_len < sizeof(*src))
+ return -EPROTO;
+
+ data += sizeof(*src);
+ data_len -= sizeof(*src);
+
+ dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ if (!dst)
+ continue;
+
+ ath10k_wmi_pull_pdev_stats_base(&src->base, dst);
+ ath10k_wmi_pull_pdev_stats_tx(&src->tx, dst);
+ ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst);
+ list_add_tail(&dst->list, &stats->pdevs);
+ }
+
+ for (i = 0; i < num_vdev_stats; i++) {
+ const struct wmi_tlv_vdev_stats *src;
+ struct ath10k_fw_stats_vdev *dst;
+
+ src = data;
+ if (data_len < sizeof(*src))
+ return -EPROTO;
+
+ data += sizeof(*src);
+ data_len -= sizeof(*src);
+
+ dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ if (!dst)
+ continue;
+
+ ath10k_wmi_tlv_pull_vdev_stats(src, dst);
+ list_add_tail(&dst->list, &stats->vdevs);
+ }
+
+ for (i = 0; i < num_peer_stats; i++) {
+ const struct wmi_10x_peer_stats *src;
+ struct ath10k_fw_stats_peer *dst;
+
+ src = data;
+ if (data_len < sizeof(*src))
+ return -EPROTO;
+
+ data += sizeof(*src);
+ data_len -= sizeof(*src);
+
+ dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ if (!dst)
+ continue;
+
+ ath10k_wmi_pull_peer_stats(&src->old, dst);
+ dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
+ list_add_tail(&dst->list, &stats->peers);
+ }

kfree(tb);
return 0;
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
index de68fe7..d7a31e1 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
@@ -1439,6 +1439,15 @@ struct wmi_tlv_sta_keepalive_cmd {
__le32 interval; /* in seconds */
} __packed;

+struct wmi_tlv_stats_ev {
+ __le32 stats_id; /* WMI_STAT_ */
+ __le32 num_pdev_stats;
+ __le32 num_vdev_stats;
+ __le32 num_peer_stats;
+ __le32 num_bcnflt_stats;
+ __le32 num_chan_stats;
+} __packed;
+
void ath10k_wmi_tlv_attach(struct ath10k *ar);

#endif
--
1.8.5.3


2015-01-30 09:48:22

by Michal Kazior

[permalink] [raw]
Subject: [PATCH 1/4] ath10k: add vdev stats processing

New qca6174 wmi-tlv firmware supports vdev stats.
This patch adds support for it in the debug
frontend.

Signed-off-by: Michal Kazior <[email protected]>
---
drivers/net/wireless/ath/ath10k/core.h | 20 +++++++
drivers/net/wireless/ath/ath10k/debug.c | 96 +++++++++++++++++++++++++++++++++
2 files changed, 116 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index abb3203..dbc6c51 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -159,6 +159,25 @@ struct ath10k_fw_stats_peer {
u32 peer_rx_rate; /* 10x only */
};

+struct ath10k_fw_stats_vdev {
+ struct list_head list;
+
+ u32 vdev_id;
+ u32 beacon_snr;
+ u32 data_snr;
+ u32 num_tx_frames[4];
+ u32 num_rx_frames;
+ u32 num_tx_frames_retries[4];
+ u32 num_tx_frames_failures[4];
+ u32 num_rts_fail;
+ u32 num_rts_success;
+ u32 num_rx_err;
+ u32 num_rx_discard;
+ u32 num_tx_not_acked;
+ u32 tx_rate_history[10];
+ u32 beacon_rssi_history[10];
+};
+
struct ath10k_fw_stats_pdev {
struct list_head list;

@@ -220,6 +239,7 @@ struct ath10k_fw_stats_pdev {

struct ath10k_fw_stats {
struct list_head pdevs;
+ struct list_head vdevs;
struct list_head peers;
};

diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 42b2e49..f0a6b93 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -243,6 +243,16 @@ static void ath10k_debug_fw_stats_pdevs_free(struct list_head *head)
}
}

+static void ath10k_debug_fw_stats_vdevs_free(struct list_head *head)
+{
+ struct ath10k_fw_stats_vdev *i, *tmp;
+
+ list_for_each_entry_safe(i, tmp, head, list) {
+ list_del(&i->list);
+ kfree(i);
+ }
+}
+
static void ath10k_debug_fw_stats_peers_free(struct list_head *head)
{
struct ath10k_fw_stats_peer *i, *tmp;
@@ -258,6 +268,7 @@ static void ath10k_debug_fw_stats_reset(struct ath10k *ar)
spin_lock_bh(&ar->data_lock);
ar->debug.fw_stats_done = false;
ath10k_debug_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
+ ath10k_debug_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
ath10k_debug_fw_stats_peers_free(&ar->debug.fw_stats.peers);
spin_unlock_bh(&ar->data_lock);
}
@@ -273,14 +284,27 @@ static size_t ath10k_debug_fw_stats_num_peers(struct list_head *head)
return num;
}

+static size_t ath10k_debug_fw_stats_num_vdevs(struct list_head *head)
+{
+ struct ath10k_fw_stats_vdev *i;
+ size_t num = 0;
+
+ list_for_each_entry(i, head, list)
+ ++num;
+
+ return num;
+}
+
void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
{
struct ath10k_fw_stats stats = {};
bool is_start, is_started, is_end;
size_t num_peers;
+ size_t num_vdevs;
int ret;

INIT_LIST_HEAD(&stats.pdevs);
+ INIT_LIST_HEAD(&stats.vdevs);
INIT_LIST_HEAD(&stats.peers);

spin_lock_bh(&ar->data_lock);
@@ -308,6 +332,7 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
}

num_peers = ath10k_debug_fw_stats_num_peers(&ar->debug.fw_stats.peers);
+ num_vdevs = ath10k_debug_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs);
is_start = (list_empty(&ar->debug.fw_stats.pdevs) &&
!list_empty(&stats.pdevs));
is_end = (!list_empty(&ar->debug.fw_stats.pdevs) &&
@@ -330,7 +355,13 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
goto free;
}

+ if (num_vdevs >= BITS_PER_LONG) {
+ ath10k_warn(ar, "dropping fw vdev stats\n");
+ goto free;
+ }
+
list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers);
+ list_splice_tail_init(&stats.vdevs, &ar->debug.fw_stats.vdevs);
}

complete(&ar->debug.fw_stats_complete);
@@ -340,6 +371,7 @@ free:
* resources if that is not the case.
*/
ath10k_debug_fw_stats_pdevs_free(&stats.pdevs);
+ ath10k_debug_fw_stats_vdevs_free(&stats.vdevs);
ath10k_debug_fw_stats_peers_free(&stats.peers);

unlock:
@@ -395,8 +427,11 @@ static void ath10k_fw_stats_fill(struct ath10k *ar,
unsigned int len = 0;
unsigned int buf_len = ATH10K_FW_STATS_BUF_SIZE;
const struct ath10k_fw_stats_pdev *pdev;
+ const struct ath10k_fw_stats_vdev *vdev;
const struct ath10k_fw_stats_peer *peer;
size_t num_peers;
+ size_t num_vdevs;
+ int i;

spin_lock_bh(&ar->data_lock);

@@ -408,6 +443,7 @@ static void ath10k_fw_stats_fill(struct ath10k *ar,
}

num_peers = ath10k_debug_fw_stats_num_peers(&fw_stats->peers);
+ num_vdevs = ath10k_debug_fw_stats_num_vdevs(&fw_stats->vdevs);

len += scnprintf(buf + len, buf_len - len, "\n");
len += scnprintf(buf + len, buf_len - len, "%30s\n",
@@ -531,6 +567,65 @@ static void ath10k_fw_stats_fill(struct ath10k *ar,

len += scnprintf(buf + len, buf_len - len, "\n");
len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
+ "ath10k VDEV stats", num_vdevs);
+ len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
+ "=================");
+
+ list_for_each_entry(vdev, &fw_stats->vdevs, list) {
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "vdev id", vdev->vdev_id);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "beacon snr", vdev->beacon_snr);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "data snr", vdev->data_snr);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "num rx frames", vdev->num_rx_frames);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "num rts fail", vdev->num_rts_fail);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "num rts success", vdev->num_rts_success);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "num rx err", vdev->num_rx_err);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "num rx discard", vdev->num_rx_discard);
+ len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
+ "num tx not acked", vdev->num_tx_not_acked);
+
+ for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames); i++)
+ len += scnprintf(buf + len, buf_len - len,
+ "%25s [%02d] %u\n",
+ "num tx frames", i,
+ vdev->num_tx_frames[i]);
+
+ for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_retries); i++)
+ len += scnprintf(buf + len, buf_len - len,
+ "%25s [%02d] %u\n",
+ "num tx frames retries", i,
+ vdev->num_tx_frames_retries[i]);
+
+ for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_failures); i++)
+ len += scnprintf(buf + len, buf_len - len,
+ "%25s [%02d] %u\n",
+ "num tx frames failures", i,
+ vdev->num_tx_frames_failures[i]);
+
+ for (i = 0 ; i < ARRAY_SIZE(vdev->tx_rate_history); i++)
+ len += scnprintf(buf + len, buf_len - len,
+ "%25s [%02d] 0x%08x\n",
+ "tx rate history", i,
+ vdev->tx_rate_history[i]);
+
+ for (i = 0 ; i < ARRAY_SIZE(vdev->beacon_rssi_history); i++)
+ len += scnprintf(buf + len, buf_len - len,
+ "%25s [%02d] %u\n",
+ "beacon rssi history", i,
+ vdev->beacon_rssi_history[i]);
+
+ len += scnprintf(buf + len, buf_len - len, "\n");
+ }
+
+ len += scnprintf(buf + len, buf_len - len, "\n");
+ len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
"ath10k PEER stats", num_peers);
len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
"=================");
@@ -1886,6 +1981,7 @@ int ath10k_debug_create(struct ath10k *ar)
return -ENOMEM;

INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
+ INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);
INIT_LIST_HEAD(&ar->debug.fw_stats.peers);

return 0;
--
1.8.5.3


2015-02-16 07:08:29

by Michal Kazior

[permalink] [raw]
Subject: Re: [PATCH 0/4] ath10k: implement fw stats for wmi-tlv

On 15 February 2015 at 16:15, Kalle Valo <[email protected]> wrote:
> Michal Kazior <[email protected]> writes:
>
>> There are some slight differences in fw stats
>> (sic) in wmi-tlv.
>>
>> Firmware has changed the querying scheme and no
>> longer requires the ping-pong to get all stats.
>> The patchset doesn't change this behaviour so with
>> wmi-tlv it's possible to see the following
>> warnings when reading fw stats:
>>
>> ath10k_pci 0000:00:06.0: received unsolicited stats update event
>>
>> The logic in ath10k still produces correct results
>> so this is harmless.
>>
>> I wonder how to deal with this in a sane way. An
>> `if (op_ver == WMI_TLV)` is a little bad but
>> having a new ar->fw_feature flag just for a debug
>> facility like this is a bit silly. Or we can just
>> drop the warning and leave a comment. Ideas?
>
> I think we could just drop the warning and leave a comment. That
> shouldn't break anything, right?

We end up performing a few extra wmi exchanges but this is harmless.
Having an extra condition to handle this cleanly with wmi-tlv/qca6174
seems a bit of an overkill.

The warning was just an explicit way of specifying what we expected of
the fw stats exchange logic. The assertion is no longer valid so it
can go away.


Michał

2015-02-05 09:21:29

by Michal Kazior

[permalink] [raw]
Subject: Re: [PATCH 0/4] ath10k: implement fw stats for wmi-tlv

On 4 February 2015 at 09:49, Kalle Valo <[email protected]> wrote:
> Michal Kazior <[email protected]> writes:
>
>> There are some slight differences in fw stats
>> (sic) in wmi-tlv.
>>
>> Firmware has changed the querying scheme and no
>> longer requires the ping-pong to get all stats.
>> The patchset doesn't change this behaviour so with
>> wmi-tlv it's possible to see the following
>> warnings when reading fw stats:
>>
>> ath10k_pci 0000:00:06.0: received unsolicited stats update event
>>
>> The logic in ath10k still produces correct results
>> so this is harmless.
>>
>> I wonder how to deal with this in a sane way. An
>> `if (op_ver == WMI_TLV)` is a little bad but
>> having a new ar->fw_feature flag just for a debug
>> facility like this is a bit silly. Or we can just
>> drop the warning and leave a comment. Ideas?
>
> I think we could just remove the warning.
>
>> Michal Kazior (4):
>> ath10k: add vdev stats processing
>> ath10k: change request stats command prototype
>> ath10k: add more wmi fw stat defines
>> ath10k: implement fw stats for wmi-tlv
>
> There was a conflict in patch 2 but 3-way merge solved it automatically.
> Please check the result in the pending branch.

Looks good, thanks!


Michał

2015-02-04 08:50:07

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 0/4] ath10k: implement fw stats for wmi-tlv

Michal Kazior <[email protected]> writes:

> There are some slight differences in fw stats
> (sic) in wmi-tlv.
>
> Firmware has changed the querying scheme and no
> longer requires the ping-pong to get all stats.
> The patchset doesn't change this behaviour so with
> wmi-tlv it's possible to see the following
> warnings when reading fw stats:
>
> ath10k_pci 0000:00:06.0: received unsolicited stats update event
>
> The logic in ath10k still produces correct results
> so this is harmless.
>
> I wonder how to deal with this in a sane way. An
> `if (op_ver == WMI_TLV)` is a little bad but
> having a new ar->fw_feature flag just for a debug
> facility like this is a bit silly. Or we can just
> drop the warning and leave a comment. Ideas?

I think we could just remove the warning.

> Michal Kazior (4):
> ath10k: add vdev stats processing
> ath10k: change request stats command prototype
> ath10k: add more wmi fw stat defines
> ath10k: implement fw stats for wmi-tlv

There was a conflict in patch 2 but 3-way merge solved it automatically.
Please check the result in the pending branch.

--
Kalle Valo

2015-02-15 15:15:07

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 0/4] ath10k: implement fw stats for wmi-tlv

Michal Kazior <[email protected]> writes:

> There are some slight differences in fw stats
> (sic) in wmi-tlv.
>
> Firmware has changed the querying scheme and no
> longer requires the ping-pong to get all stats.
> The patchset doesn't change this behaviour so with
> wmi-tlv it's possible to see the following
> warnings when reading fw stats:
>
> ath10k_pci 0000:00:06.0: received unsolicited stats update event
>
> The logic in ath10k still produces correct results
> so this is harmless.
>
> I wonder how to deal with this in a sane way. An
> `if (op_ver == WMI_TLV)` is a little bad but
> having a new ar->fw_feature flag just for a debug
> facility like this is a bit silly. Or we can just
> drop the warning and leave a comment. Ideas?

I think we could just drop the warning and leave a comment. That
shouldn't break anything, right?

> Michal Kazior (4):
> ath10k: add vdev stats processing
> ath10k: change request stats command prototype
> ath10k: add more wmi fw stat defines
> ath10k: implement fw stats for wmi-tlv

Thanks, applied to ath.git.

--
Kalle Valo