ath10k: handle 10.4 firmware wmi swba event
authorRaja Mani <rmani@qti.qualcomm.com>
Mon, 22 Jun 2015 14:52:21 +0000 (20:22 +0530)
committerKalle Valo <kvalo@qca.qualcomm.com>
Thu, 2 Jul 2015 05:47:12 +0000 (08:47 +0300)
10.4 firmware swba event payload has space to accommodate upto
512 client traffic indication info & one p2p noa descriptor.
It's is not matching with exiting swba event format defined for
non 10.4 firmware. Non 10.4 firmware swba event format is designed
to support only upto only 128 client and four p2p notice of absence
descriptor.

following changes are done in this patch to enable ath10k to handle
10.4 firmware swba event,

 - link generic ath10k_wmi_event_host_swba() to handle 10.4 swba
   event in 10.4 wmi rx handler.

 - add 10.4 specific swba event structure wmi_10_4_host_swba_event.

 - new function ath10k_wmi_10_4_op_pull_swba_ev() to parse
   10.4 swba event.

 - increase tim_bitmap[] size in ath10k_vif to 64 to hold 512 station
   power save state.

Signed-off-by: Raja Mani <rmani@qti.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/ath10k/core.h
drivers/net/wireless/ath/ath10k/wmi.c
drivers/net/wireless/ath/ath10k/wmi.h

index 58b02ae817062ee34bd2b102e474c7b41ff00c71..86c4015270e9d3127a7ad6cf1debb74e300ff638 100644 (file)
@@ -328,8 +328,8 @@ struct ath10k_vif {
                        u32 uapsd;
                } sta;
                struct {
-                       /* 127 stations; wmi limit */
-                       u8 tim_bitmap[16];
+                       /* 512 stations */
+                       u8 tim_bitmap[64];
                        u8 tim_len;
                        u32 ssid_len;
                        u8 ssid[IEEE80211_MAX_SSID_LEN];
index 228c3dd6713a2d5df5acef43333af740de3c4823..7f9800ac15ec3e3ff2251f51c16492cee8acea48 100644 (file)
@@ -3034,6 +3034,63 @@ static int ath10k_wmi_op_pull_swba_ev(struct ath10k *ar, struct sk_buff *skb,
        return 0;
 }
 
+static int ath10k_wmi_10_4_op_pull_swba_ev(struct ath10k *ar,
+                                          struct sk_buff *skb,
+                                          struct wmi_swba_ev_arg *arg)
+{
+       struct wmi_10_4_host_swba_event *ev = (void *)skb->data;
+       u32 map, tim_len;
+       size_t i;
+
+       if (skb->len < sizeof(*ev))
+               return -EPROTO;
+
+       skb_pull(skb, sizeof(*ev));
+       arg->vdev_map = ev->vdev_map;
+
+       for (i = 0, map = __le32_to_cpu(ev->vdev_map); map; map >>= 1) {
+               if (!(map & BIT(0)))
+                       continue;
+
+               /* If this happens there were some changes in firmware and
+                * ath10k should update the max size of tim_info array.
+                */
+               if (WARN_ON_ONCE(i == ARRAY_SIZE(arg->tim_info)))
+                       break;
+
+               if (__le32_to_cpu(ev->bcn_info[i].tim_info.tim_len) >
+                     sizeof(ev->bcn_info[i].tim_info.tim_bitmap)) {
+                       ath10k_warn(ar, "refusing to parse invalid swba structure\n");
+                       return -EPROTO;
+               }
+
+               tim_len = __le32_to_cpu(ev->bcn_info[i].tim_info.tim_len);
+               if (tim_len) {
+                       /* Exclude 4 byte guard length */
+                       tim_len -= 4;
+                       arg->tim_info[i].tim_len = __cpu_to_le32(tim_len);
+               } else {
+                       arg->tim_info[i].tim_len = 0;
+               }
+
+               arg->tim_info[i].tim_mcast = ev->bcn_info[i].tim_info.tim_mcast;
+               arg->tim_info[i].tim_bitmap =
+                               ev->bcn_info[i].tim_info.tim_bitmap;
+               arg->tim_info[i].tim_changed =
+                               ev->bcn_info[i].tim_info.tim_changed;
+               arg->tim_info[i].tim_num_ps_pending =
+                               ev->bcn_info[i].tim_info.tim_num_ps_pending;
+
+               /* 10.4 firmware doesn't have p2p support. notice of absence
+                * info can be ignored for now.
+                */
+
+               i++;
+       }
+
+       return 0;
+}
+
 void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
 {
        struct wmi_swba_ev_arg arg = {};
@@ -4368,6 +4425,9 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb)
        case WMI_10_4_READY_EVENTID:
                ath10k_wmi_event_ready(ar, skb);
                break;
+       case WMI_10_4_HOST_SWBA_EVENTID:
+               ath10k_wmi_event_host_swba(ar, skb);
+               break;
        default:
                ath10k_warn(ar, "Unknown eventid: %d\n", id);
                break;
@@ -6299,6 +6359,7 @@ static const struct wmi_ops wmi_10_4_ops = {
        .rx = ath10k_wmi_10_4_op_rx,
        .map_svc = wmi_10_4_svc_map,
        .pull_mgmt_rx = ath10k_wmi_10_4_op_pull_mgmt_rx_ev,
+       .pull_swba = ath10k_wmi_10_4_op_pull_swba_ev,
        .pull_svc_rdy = ath10k_wmi_main_op_pull_svc_rdy_ev,
        .pull_rdy = ath10k_wmi_op_pull_rdy_ev,
        .gen_init = ath10k_wmi_10_4_op_gen_init,
index 7c4a15f1ae77da20ac4d85b8491967a242021a73..395742d3ff615bcc0677f5215f4be5ee5ac52fe8 100644 (file)
@@ -5199,6 +5199,47 @@ struct wmi_host_swba_event {
        struct wmi_bcn_info bcn_info[0];
 } __packed;
 
+/* 16 words = 512 client + 1 word = for guard */
+#define WMI_10_4_TIM_BITMAP_ARRAY_SIZE 17
+
+struct wmi_10_4_tim_info {
+       __le32 tim_len;
+       __le32 tim_mcast;
+       __le32 tim_bitmap[WMI_10_4_TIM_BITMAP_ARRAY_SIZE];
+       __le32 tim_changed;
+       __le32 tim_num_ps_pending;
+} __packed;
+
+#define WMI_10_4_P2P_MAX_NOA_DESCRIPTORS 1
+
+struct wmi_10_4_p2p_noa_info {
+       /* Bit 0 - Flag to indicate an update in NOA schedule
+        * Bits 7-1 - Reserved
+        */
+       u8 changed;
+       /* NOA index */
+       u8 index;
+       /* Bit 0 - Opp PS state of the AP
+        * Bits 1-7 - Ctwindow in TUs
+        */
+       u8 ctwindow_oppps;
+       /* Number of NOA descriptors */
+       u8 num_descriptors;
+
+       struct wmi_p2p_noa_descriptor
+               noa_descriptors[WMI_10_4_P2P_MAX_NOA_DESCRIPTORS];
+} __packed;
+
+struct wmi_10_4_bcn_info {
+       struct wmi_10_4_tim_info tim_info;
+       struct wmi_10_4_p2p_noa_info p2p_noa_info;
+} __packed;
+
+struct wmi_10_4_host_swba_event {
+       __le32 vdev_map;
+       struct wmi_10_4_bcn_info bcn_info[0];
+} __packed;
+
 #define WMI_MAX_AP_VDEV 16
 
 struct wmi_tbtt_offset_event {