aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2015-01-24 05:14:49 -0500
committerKalle Valo <kvalo@qca.qualcomm.com>2015-01-27 09:04:52 -0500
commit20de2229c634382777eb3b8fc54a34be9669ff8a (patch)
treee801cf2621b9e39f70d8373cbdf12f70146bf5d0 /drivers/net/wireless
parentb91251fbe88c9db1a7af29cfe49ca50aa4da9cd2 (diff)
ath10k: fix 10.2 fw stats parsing
Both 10.2 firmware binaries 10.2-00082-4 and 10.2.4.20 have introduced ABI changes to fw_stats each. This caused fw_stats to output wrong data. Define new structures and use them to parse the statistics correctly. Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c162
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h52
2 files changed, 212 insertions, 2 deletions
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index ce095dac5b44..fb1e2d1f343c 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1871,6 +1871,164 @@ static int ath10k_wmi_10x_op_pull_fw_stats(struct ath10k *ar,
1871 return 0; 1871 return 0;
1872} 1872}
1873 1873
1874static int ath10k_wmi_10_2_op_pull_fw_stats(struct ath10k *ar,
1875 struct sk_buff *skb,
1876 struct ath10k_fw_stats *stats)
1877{
1878 const struct wmi_10_2_stats_event *ev = (void *)skb->data;
1879 u32 num_pdev_stats;
1880 u32 num_pdev_ext_stats;
1881 u32 num_vdev_stats;
1882 u32 num_peer_stats;
1883 int i;
1884
1885 if (!skb_pull(skb, sizeof(*ev)))
1886 return -EPROTO;
1887
1888 num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
1889 num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats);
1890 num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
1891 num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
1892
1893 for (i = 0; i < num_pdev_stats; i++) {
1894 const struct wmi_10_2_pdev_stats *src;
1895 struct ath10k_fw_stats_pdev *dst;
1896
1897 src = (void *)skb->data;
1898 if (!skb_pull(skb, sizeof(*src)))
1899 return -EPROTO;
1900
1901 dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
1902 if (!dst)
1903 continue;
1904
1905 ath10k_wmi_pull_pdev_stats_base(&src->base, dst);
1906 ath10k_wmi_pull_pdev_stats_tx(&src->tx, dst);
1907 ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst);
1908 ath10k_wmi_pull_pdev_stats_extra(&src->extra, dst);
1909 /* FIXME: expose 10.2 specific values */
1910
1911 list_add_tail(&dst->list, &stats->pdevs);
1912 }
1913
1914 for (i = 0; i < num_pdev_ext_stats; i++) {
1915 const struct wmi_10_2_pdev_ext_stats *src;
1916
1917 src = (void *)skb->data;
1918 if (!skb_pull(skb, sizeof(*src)))
1919 return -EPROTO;
1920
1921 /* FIXME: expose values to userspace
1922 *
1923 * Note: Even though this loop seems to do nothing it is
1924 * required to parse following sub-structures properly.
1925 */
1926 }
1927
1928 /* fw doesn't implement vdev stats */
1929
1930 for (i = 0; i < num_peer_stats; i++) {
1931 const struct wmi_10_2_peer_stats *src;
1932 struct ath10k_fw_stats_peer *dst;
1933
1934 src = (void *)skb->data;
1935 if (!skb_pull(skb, sizeof(*src)))
1936 return -EPROTO;
1937
1938 dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
1939 if (!dst)
1940 continue;
1941
1942 ath10k_wmi_pull_peer_stats(&src->old, dst);
1943
1944 dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
1945 /* FIXME: expose 10.2 specific values */
1946
1947 list_add_tail(&dst->list, &stats->peers);
1948 }
1949
1950 return 0;
1951}
1952
1953static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar,
1954 struct sk_buff *skb,
1955 struct ath10k_fw_stats *stats)
1956{
1957 const struct wmi_10_2_stats_event *ev = (void *)skb->data;
1958 u32 num_pdev_stats;
1959 u32 num_pdev_ext_stats;
1960 u32 num_vdev_stats;
1961 u32 num_peer_stats;
1962 int i;
1963
1964 if (!skb_pull(skb, sizeof(*ev)))
1965 return -EPROTO;
1966
1967 num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
1968 num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats);
1969 num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
1970 num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
1971
1972 for (i = 0; i < num_pdev_stats; i++) {
1973 const struct wmi_10_2_pdev_stats *src;
1974 struct ath10k_fw_stats_pdev *dst;
1975
1976 src = (void *)skb->data;
1977 if (!skb_pull(skb, sizeof(*src)))
1978 return -EPROTO;
1979
1980 dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
1981 if (!dst)
1982 continue;
1983
1984 ath10k_wmi_pull_pdev_stats_base(&src->base, dst);
1985 ath10k_wmi_pull_pdev_stats_tx(&src->tx, dst);
1986 ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst);
1987 ath10k_wmi_pull_pdev_stats_extra(&src->extra, dst);
1988 /* FIXME: expose 10.2 specific values */
1989
1990 list_add_tail(&dst->list, &stats->pdevs);
1991 }
1992
1993 for (i = 0; i < num_pdev_ext_stats; i++) {
1994 const struct wmi_10_2_pdev_ext_stats *src;
1995
1996 src = (void *)skb->data;
1997 if (!skb_pull(skb, sizeof(*src)))
1998 return -EPROTO;
1999
2000 /* FIXME: expose values to userspace
2001 *
2002 * Note: Even though this loop seems to do nothing it is
2003 * required to parse following sub-structures properly.
2004 */
2005 }
2006
2007 /* fw doesn't implement vdev stats */
2008
2009 for (i = 0; i < num_peer_stats; i++) {
2010 const struct wmi_10_2_4_peer_stats *src;
2011 struct ath10k_fw_stats_peer *dst;
2012
2013 src = (void *)skb->data;
2014 if (!skb_pull(skb, sizeof(*src)))
2015 return -EPROTO;
2016
2017 dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
2018 if (!dst)
2019 continue;
2020
2021 ath10k_wmi_pull_peer_stats(&src->common.old, dst);
2022
2023 dst->peer_rx_rate = __le32_to_cpu(src->common.peer_rx_rate);
2024 /* FIXME: expose 10.2 specific values */
2025
2026 list_add_tail(&dst->list, &stats->peers);
2027 }
2028
2029 return 0;
2030}
2031
1874void ath10k_wmi_event_update_stats(struct ath10k *ar, struct sk_buff *skb) 2032void ath10k_wmi_event_update_stats(struct ath10k *ar, struct sk_buff *skb)
1875{ 2033{
1876 ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n"); 2034 ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n");
@@ -5121,6 +5279,7 @@ static const struct wmi_ops wmi_10_1_ops = {
5121 5279
5122static const struct wmi_ops wmi_10_2_ops = { 5280static const struct wmi_ops wmi_10_2_ops = {
5123 .rx = ath10k_wmi_10_2_op_rx, 5281 .rx = ath10k_wmi_10_2_op_rx,
5282 .pull_fw_stats = ath10k_wmi_10_2_op_pull_fw_stats,
5124 .gen_init = ath10k_wmi_10_2_op_gen_init, 5283 .gen_init = ath10k_wmi_10_2_op_gen_init,
5125 .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc, 5284 .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
5126 /* .gen_pdev_get_temperature not implemented */ 5285 /* .gen_pdev_get_temperature not implemented */
@@ -5128,7 +5287,6 @@ static const struct wmi_ops wmi_10_2_ops = {
5128 /* shared with 10.1 */ 5287 /* shared with 10.1 */
5129 .map_svc = wmi_10x_svc_map, 5288 .map_svc = wmi_10x_svc_map,
5130 .pull_svc_rdy = ath10k_wmi_10x_op_pull_svc_rdy_ev, 5289 .pull_svc_rdy = ath10k_wmi_10x_op_pull_svc_rdy_ev,
5131 .pull_fw_stats = ath10k_wmi_10x_op_pull_fw_stats,
5132 .gen_pdev_set_rd = ath10k_wmi_10x_op_gen_pdev_set_rd, 5290 .gen_pdev_set_rd = ath10k_wmi_10x_op_gen_pdev_set_rd,
5133 .gen_start_scan = ath10k_wmi_10x_op_gen_start_scan, 5291 .gen_start_scan = ath10k_wmi_10x_op_gen_start_scan,
5134 5292
@@ -5180,6 +5338,7 @@ static const struct wmi_ops wmi_10_2_ops = {
5180 5338
5181static const struct wmi_ops wmi_10_2_4_ops = { 5339static const struct wmi_ops wmi_10_2_4_ops = {
5182 .rx = ath10k_wmi_10_2_op_rx, 5340 .rx = ath10k_wmi_10_2_op_rx,
5341 .pull_fw_stats = ath10k_wmi_10_2_4_op_pull_fw_stats,
5183 .gen_init = ath10k_wmi_10_2_op_gen_init, 5342 .gen_init = ath10k_wmi_10_2_op_gen_init,
5184 .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc, 5343 .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
5185 .gen_pdev_get_temperature = ath10k_wmi_10_2_op_gen_pdev_get_temperature, 5344 .gen_pdev_get_temperature = ath10k_wmi_10_2_op_gen_pdev_get_temperature,
@@ -5187,7 +5346,6 @@ static const struct wmi_ops wmi_10_2_4_ops = {
5187 /* shared with 10.1 */ 5346 /* shared with 10.1 */
5188 .map_svc = wmi_10x_svc_map, 5347 .map_svc = wmi_10x_svc_map,
5189 .pull_svc_rdy = ath10k_wmi_10x_op_pull_svc_rdy_ev, 5348 .pull_svc_rdy = ath10k_wmi_10x_op_pull_svc_rdy_ev,
5190 .pull_fw_stats = ath10k_wmi_10x_op_pull_fw_stats,
5191 .gen_pdev_set_rd = ath10k_wmi_10x_op_gen_pdev_set_rd, 5349 .gen_pdev_set_rd = ath10k_wmi_10x_op_gen_pdev_set_rd,
5192 .gen_start_scan = ath10k_wmi_10x_op_gen_start_scan, 5350 .gen_start_scan = ath10k_wmi_10x_op_gen_start_scan,
5193 5351
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 109ed623b82f..0514b1a525ff 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -3121,6 +3121,16 @@ struct wmi_stats_event {
3121 u8 data[0]; 3121 u8 data[0];
3122} __packed; 3122} __packed;
3123 3123
3124struct wmi_10_2_stats_event {
3125 __le32 stats_id; /* %WMI_REQUEST_ */
3126 __le32 num_pdev_stats;
3127 __le32 num_pdev_ext_stats;
3128 __le32 num_vdev_stats;
3129 __le32 num_peer_stats;
3130 __le32 num_bcnflt_stats;
3131 u8 data[0];
3132} __packed;
3133
3124/* 3134/*
3125 * PDEV statistics 3135 * PDEV statistics
3126 * TODO: add all PDEV stats here 3136 * TODO: add all PDEV stats here
@@ -3159,6 +3169,22 @@ struct wmi_10x_pdev_stats {
3159 struct wmi_pdev_stats_extra extra; 3169 struct wmi_pdev_stats_extra extra;
3160} __packed; 3170} __packed;
3161 3171
3172struct wmi_pdev_stats_mem {
3173 __le32 dram_free;
3174 __le32 iram_free;
3175} __packed;
3176
3177struct wmi_10_2_pdev_stats {
3178 struct wmi_pdev_stats_base base;
3179 struct wmi_pdev_stats_tx tx;
3180 __le32 mc_drop;
3181 struct wmi_pdev_stats_rx rx;
3182 __le32 pdev_rx_timeout;
3183 struct wmi_pdev_stats_mem mem;
3184 struct wmi_pdev_stats_peer peer;
3185 struct wmi_pdev_stats_extra extra;
3186} __packed;
3187
3162/* 3188/*
3163 * VDEV statistics 3189 * VDEV statistics
3164 * TODO: add all VDEV stats here 3190 * TODO: add all VDEV stats here
@@ -3182,6 +3208,32 @@ struct wmi_10x_peer_stats {
3182 __le32 peer_rx_rate; 3208 __le32 peer_rx_rate;
3183} __packed; 3209} __packed;
3184 3210
3211struct wmi_10_2_peer_stats {
3212 struct wmi_peer_stats old;
3213 __le32 peer_rx_rate;
3214 __le32 current_per;
3215 __le32 retries;
3216 __le32 tx_rate_count;
3217 __le32 max_4ms_frame_len;
3218 __le32 total_sub_frames;
3219 __le32 tx_bytes;
3220 __le32 num_pkt_loss_overflow[4];
3221 __le32 num_pkt_loss_excess_retry[4];
3222} __packed;
3223
3224struct wmi_10_2_4_peer_stats {
3225 struct wmi_10_2_peer_stats common;
3226 __le32 unknown_value; /* FIXME: what is this word? */
3227} __packed;
3228
3229struct wmi_10_2_pdev_ext_stats {
3230 __le32 rx_rssi_comb;
3231 __le32 rx_rssi[4];
3232 __le32 rx_mcs[10];
3233 __le32 tx_mcs[10];
3234 __le32 ack_rssi;
3235} __packed;
3236
3185struct wmi_vdev_create_cmd { 3237struct wmi_vdev_create_cmd {
3186 __le32 vdev_id; 3238 __le32 vdev_id;
3187 __le32 vdev_type; 3239 __le32 vdev_type;