mac80211: add pending ath9k/ath10k patches
[openwrt.git] / package / kernel / mac80211 / patches / 305-ath10k-add-fw_stats-support-to-10.4-firmware.patch
1 From: Manikanta Pubbisetty <c_mpubbi@qti.qualcomm.com>
2 Date: Wed, 28 Oct 2015 21:38:33 +0200
3 Subject: [PATCH] ath10k: add fw_stats support to 10.4 firmware
4
5 This patch adds support for getting firmware debug stats in 10.4 fw.
6
7 Signed-off-by: Manikanta Pubbisetty <c_mpubbi@qti.qualcomm.com>
8 Signed-off-by: Tamizh chelvam <c_traja@qti.qualcomm.com>
9 Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
10 ---
11
12 --- a/drivers/net/wireless/ath/ath10k/core.h
13 +++ b/drivers/net/wireless/ath/ath10k/core.h
14 @@ -214,6 +214,7 @@ struct ath10k_fw_stats_pdev {
15         s32 hw_queued;
16         s32 hw_reaped;
17         s32 underrun;
18 +       u32 hw_paused;
19         s32 tx_abort;
20         s32 mpdus_requed;
21         u32 tx_ko;
22 @@ -226,6 +227,16 @@ struct ath10k_fw_stats_pdev {
23         u32 pdev_resets;
24         u32 phy_underrun;
25         u32 txop_ovf;
26 +       u32 seq_posted;
27 +       u32 seq_failed_queueing;
28 +       u32 seq_completed;
29 +       u32 seq_restarted;
30 +       u32 mu_seq_posted;
31 +       u32 mpdus_sw_flush;
32 +       u32 mpdus_hw_filter;
33 +       u32 mpdus_truncated;
34 +       u32 mpdus_ack_failed;
35 +       u32 mpdus_expired;
36  
37         /* PDEV RX stats */
38         s32 mid_ppdu_route_change;
39 @@ -242,6 +253,7 @@ struct ath10k_fw_stats_pdev {
40         s32 phy_errs;
41         s32 phy_err_drop;
42         s32 mpdu_errs;
43 +       s32 rx_ovfl_errs;
44  };
45  
46  struct ath10k_fw_stats {
47 --- a/drivers/net/wireless/ath/ath10k/wmi.c
48 +++ b/drivers/net/wireless/ath/ath10k/wmi.c
49 @@ -2479,6 +2479,47 @@ void ath10k_wmi_pull_pdev_stats_tx(const
50         dst->txop_ovf = __le32_to_cpu(src->txop_ovf);
51  }
52  
53 +static void
54 +ath10k_wmi_10_4_pull_pdev_stats_tx(const struct wmi_10_4_pdev_stats_tx *src,
55 +                                  struct ath10k_fw_stats_pdev *dst)
56 +{
57 +       dst->comp_queued = __le32_to_cpu(src->comp_queued);
58 +       dst->comp_delivered = __le32_to_cpu(src->comp_delivered);
59 +       dst->msdu_enqued = __le32_to_cpu(src->msdu_enqued);
60 +       dst->mpdu_enqued = __le32_to_cpu(src->mpdu_enqued);
61 +       dst->wmm_drop = __le32_to_cpu(src->wmm_drop);
62 +       dst->local_enqued = __le32_to_cpu(src->local_enqued);
63 +       dst->local_freed = __le32_to_cpu(src->local_freed);
64 +       dst->hw_queued = __le32_to_cpu(src->hw_queued);
65 +       dst->hw_reaped = __le32_to_cpu(src->hw_reaped);
66 +       dst->underrun = __le32_to_cpu(src->underrun);
67 +       dst->tx_abort = __le32_to_cpu(src->tx_abort);
68 +       dst->mpdus_requed = __le32_to_cpu(src->mpdus_requed);
69 +       dst->tx_ko = __le32_to_cpu(src->tx_ko);
70 +       dst->data_rc = __le32_to_cpu(src->data_rc);
71 +       dst->self_triggers = __le32_to_cpu(src->self_triggers);
72 +       dst->sw_retry_failure = __le32_to_cpu(src->sw_retry_failure);
73 +       dst->illgl_rate_phy_err = __le32_to_cpu(src->illgl_rate_phy_err);
74 +       dst->pdev_cont_xretry = __le32_to_cpu(src->pdev_cont_xretry);
75 +       dst->pdev_tx_timeout = __le32_to_cpu(src->pdev_tx_timeout);
76 +       dst->pdev_resets = __le32_to_cpu(src->pdev_resets);
77 +       dst->phy_underrun = __le32_to_cpu(src->phy_underrun);
78 +       dst->txop_ovf = __le32_to_cpu(src->txop_ovf);
79 +       dst->hw_paused = __le32_to_cpu(src->hw_paused);
80 +       dst->seq_posted = __le32_to_cpu(src->seq_posted);
81 +       dst->seq_failed_queueing =
82 +               __le32_to_cpu(src->seq_failed_queueing);
83 +       dst->seq_completed = __le32_to_cpu(src->seq_completed);
84 +       dst->seq_restarted = __le32_to_cpu(src->seq_restarted);
85 +       dst->mu_seq_posted = __le32_to_cpu(src->mu_seq_posted);
86 +       dst->mpdus_sw_flush = __le32_to_cpu(src->mpdus_sw_flush);
87 +       dst->mpdus_hw_filter = __le32_to_cpu(src->mpdus_hw_filter);
88 +       dst->mpdus_truncated = __le32_to_cpu(src->mpdus_truncated);
89 +       dst->mpdus_ack_failed = __le32_to_cpu(src->mpdus_ack_failed);
90 +       dst->mpdus_hw_filter = __le32_to_cpu(src->mpdus_hw_filter);
91 +       dst->mpdus_expired = __le32_to_cpu(src->mpdus_expired);
92 +}
93 +
94  void ath10k_wmi_pull_pdev_stats_rx(const struct wmi_pdev_stats_rx *src,
95                                    struct ath10k_fw_stats_pdev *dst)
96  {
97 @@ -2789,6 +2830,86 @@ static int ath10k_wmi_10_2_4_op_pull_fw_
98         return 0;
99  }
100  
101 +static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
102 +                                           struct sk_buff *skb,
103 +                                           struct ath10k_fw_stats *stats)
104 +{
105 +       const struct wmi_10_2_stats_event *ev = (void *)skb->data;
106 +       u32 num_pdev_stats;
107 +       u32 num_pdev_ext_stats;
108 +       u32 num_vdev_stats;
109 +       u32 num_peer_stats;
110 +       int i;
111 +
112 +       if (!skb_pull(skb, sizeof(*ev)))
113 +               return -EPROTO;
114 +
115 +       num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
116 +       num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats);
117 +       num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
118 +       num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
119 +
120 +       for (i = 0; i < num_pdev_stats; i++) {
121 +               const struct wmi_10_4_pdev_stats *src;
122 +               struct ath10k_fw_stats_pdev *dst;
123 +
124 +               src = (void *)skb->data;
125 +               if (!skb_pull(skb, sizeof(*src)))
126 +                       return -EPROTO;
127 +
128 +               dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
129 +               if (!dst)
130 +                       continue;
131 +
132 +               ath10k_wmi_pull_pdev_stats_base(&src->base, dst);
133 +               ath10k_wmi_10_4_pull_pdev_stats_tx(&src->tx, dst);
134 +               ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst);
135 +               dst->rx_ovfl_errs = __le32_to_cpu(src->rx_ovfl_errs);
136 +               ath10k_wmi_pull_pdev_stats_extra(&src->extra, dst);
137 +
138 +               list_add_tail(&dst->list, &stats->pdevs);
139 +       }
140 +
141 +       for (i = 0; i < num_pdev_ext_stats; i++) {
142 +               const struct wmi_10_2_pdev_ext_stats *src;
143 +
144 +               src = (void *)skb->data;
145 +               if (!skb_pull(skb, sizeof(*src)))
146 +                       return -EPROTO;
147 +
148 +               /* FIXME: expose values to userspace
149 +                *
150 +                * Note: Even though this loop seems to do nothing it is
151 +                * required to parse following sub-structures properly.
152 +                */
153 +       }
154 +
155 +       /* fw doesn't implement vdev stats */
156 +
157 +       for (i = 0; i < num_peer_stats; i++) {
158 +               const struct wmi_10_4_peer_stats *src;
159 +               struct ath10k_fw_stats_peer *dst;
160 +
161 +               src = (void *)skb->data;
162 +               if (!skb_pull(skb, sizeof(*src)))
163 +                       return -EPROTO;
164 +
165 +               dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
166 +               if (!dst)
167 +                       continue;
168 +
169 +               ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr);
170 +               dst->peer_rssi = __le32_to_cpu(src->peer_rssi);
171 +               dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate);
172 +               dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
173 +               /* FIXME: expose 10.4 specific values */
174 +
175 +               list_add_tail(&dst->list, &stats->peers);
176 +       }
177 +
178 +       return 0;
179 +}
180 +
181  void ath10k_wmi_event_update_stats(struct ath10k *ar, struct sk_buff *skb)
182  {
183         ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n");
184 @@ -4935,6 +5056,9 @@ static void ath10k_wmi_10_4_op_rx(struct
185                 ath10k_dbg(ar, ATH10K_DBG_WMI,
186                            "received event id %d not implemented\n", id);
187                 break;
188 +       case WMI_10_4_UPDATE_STATS_EVENTID:
189 +               ath10k_wmi_event_update_stats(ar, skb);
190 +               break;
191         default:
192                 ath10k_warn(ar, "Unknown eventid: %d\n", id);
193                 break;
194 @@ -7022,6 +7146,90 @@ ath10k_wmi_op_gen_pdev_enable_adaptive_c
195         return skb;
196  }
197  
198 +void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
199 +                                     struct ath10k_fw_stats *fw_stats,
200 +                                     char *buf)
201 +{
202 +       u32 len = 0;
203 +       u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
204 +       const struct ath10k_fw_stats_pdev *pdev;
205 +       const struct ath10k_fw_stats_vdev *vdev;
206 +       const struct ath10k_fw_stats_peer *peer;
207 +       size_t num_peers;
208 +       size_t num_vdevs;
209 +
210 +       spin_lock_bh(&ar->data_lock);
211 +
212 +       pdev = list_first_entry_or_null(&fw_stats->pdevs,
213 +                                       struct ath10k_fw_stats_pdev, list);
214 +       if (!pdev) {
215 +               ath10k_warn(ar, "failed to get pdev stats\n");
216 +               goto unlock;
217 +       }
218 +
219 +       num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers);
220 +       num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs);
221 +
222 +       ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len);
223 +       ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len);
224 +       ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len);
225 +
226 +       len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
227 +                       "HW paused", pdev->hw_paused);
228 +       len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
229 +                       "Seqs posted", pdev->seq_posted);
230 +       len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
231 +                       "Seqs failed queueing", pdev->seq_failed_queueing);
232 +       len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
233 +                       "Seqs completed", pdev->seq_completed);
234 +       len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
235 +                       "Seqs restarted", pdev->seq_restarted);
236 +       len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
237 +                       "MU Seqs posted", pdev->mu_seq_posted);
238 +       len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
239 +                       "MPDUs SW flushed", pdev->mpdus_sw_flush);
240 +       len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
241 +                       "MPDUs HW filtered", pdev->mpdus_hw_filter);
242 +       len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
243 +                       "MPDUs truncated", pdev->mpdus_truncated);
244 +       len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
245 +                       "MPDUs receive no ACK", pdev->mpdus_ack_failed);
246 +       len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
247 +                       "MPDUs expired", pdev->mpdus_expired);
248 +
249 +       ath10k_wmi_fw_pdev_rx_stats_fill(pdev, buf, &len);
250 +       len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
251 +                       "Num Rx Overflow errors", pdev->rx_ovfl_errs);
252 +
253 +       len += scnprintf(buf + len, buf_len - len, "\n");
254 +       len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
255 +                       "ath10k VDEV stats", num_vdevs);
256 +       len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
257 +                               "=================");
258 +
259 +       list_for_each_entry(vdev, &fw_stats->vdevs, list) {
260 +               ath10k_wmi_fw_vdev_stats_fill(vdev, buf, &len);
261 +       }
262 +
263 +       len += scnprintf(buf + len, buf_len - len, "\n");
264 +       len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
265 +                       "ath10k PEER stats", num_peers);
266 +       len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
267 +                               "=================");
268 +
269 +       list_for_each_entry(peer, &fw_stats->peers, list) {
270 +               ath10k_wmi_fw_peer_stats_fill(peer, buf, &len);
271 +       }
272 +
273 +unlock:
274 +       spin_unlock_bh(&ar->data_lock);
275 +
276 +       if (len >= buf_len)
277 +               buf[len - 1] = 0;
278 +       else
279 +               buf[len] = 0;
280 +}
281 +
282  static const struct wmi_ops wmi_ops = {
283         .rx = ath10k_wmi_op_rx,
284         .map_svc = wmi_main_svc_map,
285 @@ -7292,6 +7500,7 @@ static const struct wmi_ops wmi_10_4_ops
286         .rx = ath10k_wmi_10_4_op_rx,
287         .map_svc = wmi_10_4_svc_map,
288  
289 +       .pull_fw_stats = ath10k_wmi_10_4_op_pull_fw_stats,
290         .pull_scan = ath10k_wmi_op_pull_scan_ev,
291         .pull_mgmt_rx = ath10k_wmi_10_4_op_pull_mgmt_rx_ev,
292         .pull_ch_info = ath10k_wmi_10_4_op_pull_ch_info_ev,
293 @@ -7341,9 +7550,11 @@ static const struct wmi_ops wmi_10_4_ops
294         .gen_addba_send = ath10k_wmi_op_gen_addba_send,
295         .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
296         .gen_delba_send = ath10k_wmi_op_gen_delba_send,
297 +       .fw_stats_fill = ath10k_wmi_10_4_op_fw_stats_fill,
298  
299         /* shared with 10.2 */
300         .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
301 +       .gen_request_stats = ath10k_wmi_op_gen_request_stats,
302  };
303  
304  int ath10k_wmi_attach(struct ath10k *ar)
305 --- a/drivers/net/wireless/ath/ath10k/wmi.h
306 +++ b/drivers/net/wireless/ath/ath10k/wmi.h
307 @@ -3866,6 +3866,111 @@ struct wmi_pdev_stats_tx {
308         __le32 txop_ovf;
309  } __packed;
310  
311 +struct wmi_10_4_pdev_stats_tx {
312 +       /* Num HTT cookies queued to dispatch list */
313 +       __le32 comp_queued;
314 +
315 +       /* Num HTT cookies dispatched */
316 +       __le32 comp_delivered;
317 +
318 +       /* Num MSDU queued to WAL */
319 +       __le32 msdu_enqued;
320 +
321 +       /* Num MPDU queue to WAL */
322 +       __le32 mpdu_enqued;
323 +
324 +       /* Num MSDUs dropped by WMM limit */
325 +       __le32 wmm_drop;
326 +
327 +       /* Num Local frames queued */
328 +       __le32 local_enqued;
329 +
330 +       /* Num Local frames done */
331 +       __le32 local_freed;
332 +
333 +       /* Num queued to HW */
334 +       __le32 hw_queued;
335 +
336 +       /* Num PPDU reaped from HW */
337 +       __le32 hw_reaped;
338 +
339 +       /* Num underruns */
340 +       __le32 underrun;
341 +
342 +       /* HW Paused. */
343 +       __le32  hw_paused;
344 +
345 +       /* Num PPDUs cleaned up in TX abort */
346 +       __le32 tx_abort;
347 +
348 +       /* Num MPDUs requed by SW */
349 +       __le32 mpdus_requed;
350 +
351 +       /* excessive retries */
352 +       __le32 tx_ko;
353 +
354 +       /* data hw rate code */
355 +       __le32 data_rc;
356 +
357 +       /* Scheduler self triggers */
358 +       __le32 self_triggers;
359 +
360 +       /* frames dropped due to excessive sw retries */
361 +       __le32 sw_retry_failure;
362 +
363 +       /* illegal rate phy errors  */
364 +       __le32 illgl_rate_phy_err;
365 +
366 +       /* wal pdev continuous xretry */
367 +       __le32 pdev_cont_xretry;
368 +
369 +       /* wal pdev tx timeouts */
370 +       __le32 pdev_tx_timeout;
371 +
372 +       /* wal pdev resets  */
373 +       __le32 pdev_resets;
374 +
375 +       /* frames dropped due to non-availability of stateless TIDs */
376 +       __le32 stateless_tid_alloc_failure;
377 +
378 +       __le32 phy_underrun;
379 +
380 +       /* MPDU is more than txop limit */
381 +       __le32 txop_ovf;
382 +
383 +       /* Number of Sequences posted */
384 +       __le32 seq_posted;
385 +
386 +       /* Number of Sequences failed queueing */
387 +       __le32 seq_failed_queueing;
388 +
389 +       /* Number of Sequences completed */
390 +       __le32 seq_completed;
391 +
392 +       /* Number of Sequences restarted */
393 +       __le32 seq_restarted;
394 +
395 +       /* Number of MU Sequences posted */
396 +       __le32 mu_seq_posted;
397 +
398 +       /* Num MPDUs flushed by SW, HWPAUSED,SW TXABORT(Reset,channel change) */
399 +       __le32 mpdus_sw_flush;
400 +
401 +       /* Num MPDUs filtered by HW, all filter condition (TTL expired) */
402 +       __le32 mpdus_hw_filter;
403 +
404 +       /* Num MPDUs truncated by PDG
405 +        * (TXOP, TBTT, PPDU_duration based on rate, dyn_bw)
406 +        */
407 +       __le32 mpdus_truncated;
408 +
409 +       /* Num MPDUs that was tried but didn't receive ACK or BA */
410 +       __le32 mpdus_ack_failed;
411 +
412 +       /* Num MPDUs that was dropped due to expiry. */
413 +       __le32 mpdus_expired;
414 +} __packed;
415 +
416  struct wmi_pdev_stats_rx {
417         /* Cnts any change in ring routing mid-ppdu */
418         __le32 mid_ppdu_route_change;
419 @@ -4039,6 +4144,16 @@ struct wmi_10_2_pdev_stats {
420         struct wmi_pdev_stats_extra extra;
421  } __packed;
422  
423 +struct wmi_10_4_pdev_stats {
424 +       struct wmi_pdev_stats_base base;
425 +       struct wmi_10_4_pdev_stats_tx tx;
426 +       struct wmi_pdev_stats_rx rx;
427 +       __le32 rx_ovfl_errs;
428 +       struct wmi_pdev_stats_mem mem;
429 +       __le32 sram_free_size;
430 +       struct wmi_pdev_stats_extra extra;
431 +} __packed;
432 +
433  /*
434   * VDEV statistics
435   * TODO: add all VDEV stats here
436 @@ -4080,6 +4195,23 @@ struct wmi_10_2_4_peer_stats {
437         __le32 unknown_value; /* FIXME: what is this word? */
438  } __packed;
439  
440 +struct wmi_10_4_peer_stats {
441 +       struct wmi_mac_addr peer_macaddr;
442 +       __le32 peer_rssi;
443 +       __le32 peer_rssi_seq_num;
444 +       __le32 peer_tx_rate;
445 +       __le32 peer_rx_rate;
446 +       __le32 current_per;
447 +       __le32 retries;
448 +       __le32 tx_rate_count;
449 +       __le32 max_4ms_frame_len;
450 +       __le32 total_sub_frames;
451 +       __le32 tx_bytes;
452 +       __le32 num_pkt_loss_overflow[4];
453 +       __le32 num_pkt_loss_excess_retry[4];
454 +       __le32 peer_rssi_changed;
455 +} __packed;
456 +
457  struct wmi_10_2_pdev_ext_stats {
458         __le32 rx_rssi_comb;
459         __le32 rx_rssi[4];
460 @@ -6201,5 +6333,8 @@ void ath10k_wmi_10x_op_fw_stats_fill(str
461                                      char *buf);
462  size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head);
463  size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head);
464 +void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
465 +                                     struct ath10k_fw_stats *fw_stats,
466 +                                     char *buf);
467  
468  #endif /* _WMI_H_ */