Commit fe3cbdfc authored by Michal Kazior's avatar Michal Kazior Committed by Kalle Valo

ath10k: implement handling of p2p noa event

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: default avatarMichal Kazior <michal.kazior@tieto.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 6a94888f
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "core.h" #include "core.h"
#include "wmi.h" #include "wmi.h"
#include "mac.h"
#include "p2p.h" #include "p2p.h"
static void ath10k_p2p_noa_ie_fill(u8 *data, size_t len, 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, ...@@ -122,3 +123,34 @@ void ath10k_p2p_noa_update(struct ath10k_vif *arvif,
__ath10k_p2p_noa_update(arvif, noa); __ath10k_p2p_noa_update(arvif, noa);
spin_unlock_bh(&ar->data_lock); 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);
}
...@@ -22,5 +22,7 @@ struct wmi_p2p_noa_info; ...@@ -22,5 +22,7 @@ struct wmi_p2p_noa_info;
void ath10k_p2p_noa_update(struct ath10k_vif *arvif, void ath10k_p2p_noa_update(struct ath10k_vif *arvif,
const struct wmi_p2p_noa_info *noa); 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 #endif
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "wmi.h" #include "wmi.h"
#include "wmi-ops.h" #include "wmi-ops.h"
#include "wmi-tlv.h" #include "wmi-tlv.h"
#include "p2p.h"
/***************/ /***************/
/* TLV helpers */ /* TLV helpers */
...@@ -63,6 +64,8 @@ static const struct wmi_tlv_policy wmi_tlv_policies[] = { ...@@ -63,6 +64,8 @@ static const struct wmi_tlv_policy wmi_tlv_policies[] = {
= { .min_len = sizeof(struct wmi_tlv_bcn_tx_status_ev) }, = { .min_len = sizeof(struct wmi_tlv_bcn_tx_status_ev) },
[WMI_TLV_TAG_STRUCT_DIAG_DATA_CONTAINER_EVENT] [WMI_TLV_TAG_STRUCT_DIAG_DATA_CONTAINER_EVENT]
= { .min_len = sizeof(struct wmi_tlv_diag_data_ev) }, = { .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 static int
...@@ -304,6 +307,41 @@ static int ath10k_wmi_tlv_event_diag(struct ath10k *ar, ...@@ -304,6 +307,41 @@ static int ath10k_wmi_tlv_event_diag(struct ath10k *ar,
return 0; 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 */ /* TLV ops */
/***********/ /***********/
...@@ -425,6 +463,9 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb) ...@@ -425,6 +463,9 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
case WMI_TLV_DIAG_EVENTID: case WMI_TLV_DIAG_EVENTID:
ath10k_wmi_tlv_event_diag(ar, skb); ath10k_wmi_tlv_event_diag(ar, skb);
break; break;
case WMI_TLV_P2P_NOA_EVENTID:
ath10k_wmi_tlv_event_p2p_noa(ar, skb);
break;
default: default:
ath10k_warn(ar, "Unknown eventid: %d\n", id); ath10k_warn(ar, "Unknown eventid: %d\n", id);
break; break;
......
...@@ -1454,6 +1454,10 @@ struct wmi_tlv_stats_ev { ...@@ -1454,6 +1454,10 @@ struct wmi_tlv_stats_ev {
__le32 num_chan_stats; __le32 num_chan_stats;
} __packed; } __packed;
struct wmi_tlv_p2p_noa_ev {
__le32 vdev_id;
} __packed;
void ath10k_wmi_tlv_attach(struct ath10k *ar); void ath10k_wmi_tlv_attach(struct ath10k *ar);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment