ath10k: implement handling of p2p noa event
authorMichal Kazior <michal.kazior@tieto.com>
Thu, 26 Feb 2015 12:23:18 +0000 (13:23 +0100)
committerKalle Valo <kvalo@qca.qualcomm.com>
Sat, 7 Mar 2015 07:57:42 +0000 (09:57 +0200)
Since new wmi-tlv firmware doesn't have SWBA event
the only way to deliver P2P NoA information is
through a new dedicated event.

This fixes P2P GO Probe Responses to include P2P
NoA when appropriate on the new firmware.

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/ath10k/p2p.c
drivers/net/wireless/ath/ath10k/p2p.h
drivers/net/wireless/ath/ath10k/wmi-tlv.c
drivers/net/wireless/ath/ath10k/wmi-tlv.h

index 79d7485e21cd330eb2860f1162056bad9d52d9fc..c0b6ffaf3ec1b22648fd7d32e0001d4f0fcdcfb1 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "core.h"
 #include "wmi.h"
+#include "mac.h"
 #include "p2p.h"
 
 static void ath10k_p2p_noa_ie_fill(u8 *data, size_t len,
@@ -122,3 +123,34 @@ void ath10k_p2p_noa_update(struct ath10k_vif *arvif,
        __ath10k_p2p_noa_update(arvif, noa);
        spin_unlock_bh(&ar->data_lock);
 }
+
+struct ath10k_p2p_noa_arg {
+       u32 vdev_id;
+       const struct wmi_p2p_noa_info *noa;
+};
+
+static void ath10k_p2p_noa_update_vdev_iter(void *data, u8 *mac,
+                                           struct ieee80211_vif *vif)
+{
+       struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+       struct ath10k_p2p_noa_arg *arg = data;
+
+       if (arvif->vdev_id != arg->vdev_id)
+               return;
+
+       ath10k_p2p_noa_update(arvif, arg->noa);
+}
+
+void ath10k_p2p_noa_update_by_vdev_id(struct ath10k *ar, u32 vdev_id,
+                                     const struct wmi_p2p_noa_info *noa)
+{
+       struct ath10k_p2p_noa_arg arg = {
+               .vdev_id = vdev_id,
+               .noa = noa,
+       };
+
+       ieee80211_iterate_active_interfaces_atomic(ar->hw,
+                                                  IEEE80211_IFACE_ITER_NORMAL,
+                                                  ath10k_p2p_noa_update_vdev_iter,
+                                                  &arg);
+}
index 171d30d699ccc7df12da56aa69a574661ed411b0..7be616e2e121a0251d3739ead6908681c2c14cd7 100644 (file)
@@ -22,5 +22,7 @@ struct wmi_p2p_noa_info;
 
 void ath10k_p2p_noa_update(struct ath10k_vif *arvif,
                           const struct wmi_p2p_noa_info *noa);
+void ath10k_p2p_noa_update_by_vdev_id(struct ath10k *ar, u32 vdev_id,
+                                     const struct wmi_p2p_noa_info *noa);
 
 #endif
index 138d80a6d3b0dd9a0693c6d3befc403f4cc2d638..939d86bf6ca12289278325f729959cbd325add5b 100644 (file)
@@ -21,6 +21,7 @@
 #include "wmi.h"
 #include "wmi-ops.h"
 #include "wmi-tlv.h"
+#include "p2p.h"
 
 /***************/
 /* TLV helpers */
@@ -63,6 +64,8 @@ static const struct wmi_tlv_policy wmi_tlv_policies[] = {
                = { .min_len = sizeof(struct wmi_tlv_bcn_tx_status_ev) },
        [WMI_TLV_TAG_STRUCT_DIAG_DATA_CONTAINER_EVENT]
                = { .min_len = sizeof(struct wmi_tlv_diag_data_ev) },
+       [WMI_TLV_TAG_STRUCT_P2P_NOA_EVENT]
+               = { .min_len = sizeof(struct wmi_tlv_p2p_noa_ev) },
 };
 
 static int
@@ -304,6 +307,41 @@ static int ath10k_wmi_tlv_event_diag(struct ath10k *ar,
        return 0;
 }
 
+static int ath10k_wmi_tlv_event_p2p_noa(struct ath10k *ar,
+                                       struct sk_buff *skb)
+{
+       const void **tb;
+       const struct wmi_tlv_p2p_noa_ev *ev;
+       const struct wmi_p2p_noa_info *noa;
+       int ret, vdev_id;
+
+       tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
+       if (IS_ERR(tb)) {
+               ret = PTR_ERR(tb);
+               ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
+               return ret;
+       }
+
+       ev = tb[WMI_TLV_TAG_STRUCT_P2P_NOA_EVENT];
+       noa = tb[WMI_TLV_TAG_STRUCT_P2P_NOA_INFO];
+
+       if (!ev || !noa) {
+               kfree(tb);
+               return -EPROTO;
+       }
+
+       vdev_id = __le32_to_cpu(ev->vdev_id);
+
+       ath10k_dbg(ar, ATH10K_DBG_WMI,
+                  "wmi tlv p2p noa vdev_id %i descriptors %hhu\n",
+                  vdev_id, noa->num_descriptors);
+
+       ath10k_p2p_noa_update_by_vdev_id(ar, vdev_id, noa);
+
+       kfree(tb);
+       return 0;
+}
+
 /***********/
 /* TLV ops */
 /***********/
@@ -425,6 +463,9 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
        case WMI_TLV_DIAG_EVENTID:
                ath10k_wmi_tlv_event_diag(ar, skb);
                break;
+       case WMI_TLV_P2P_NOA_EVENTID:
+               ath10k_wmi_tlv_event_p2p_noa(ar, skb);
+               break;
        default:
                ath10k_warn(ar, "Unknown eventid: %d\n", id);
                break;
index a6c8280cc4b194384c1abee08e8d379bd4754e23..f4a626fdf9b0c36721e72dd7307cff9ab2c7dfc9 100644 (file)
@@ -1454,6 +1454,10 @@ struct wmi_tlv_stats_ev {
        __le32 num_chan_stats;
 } __packed;
 
+struct wmi_tlv_p2p_noa_ev {
+       __le32 vdev_id;
+} __packed;
+
 void ath10k_wmi_tlv_attach(struct ath10k *ar);
 
 #endif