qcacld-3.0: Add support to get pmf bcn protect stats

Host sets WMI_REQUEST_PMF_BCN_PROTECT_STAT bit in stats_id param of
WMI_REQUEST_STATS_CMDID command. Firmware supporting pmf beacon
protection stats responds host with stats in wmi_update_stats_id
event. Host extracts PMF beacon protection stats from wmi_update_stats_id
event. Host adds PMF beacon protection stats in the response of vendor
command QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO for STA mode.

Change-Id: Ib3cb06e03dbccdb9fa1782d414ed734bd97aa309
CRs-Fixed: 2705236
This commit is contained in:
Abhishek Ambure 2020-09-02 17:28:52 +05:30 committed by snandini
parent 7f2bf137e9
commit 8c579f5a5b
8 changed files with 223 additions and 12 deletions

View File

@ -270,18 +270,36 @@ struct summary_stats {
uint32_t rx_error_cnt;
};
/**
* struct pmf_bcn_protect_stats - pmf bcn protect stats param
* @pmf_bcn_stats_valid: bcn protect stats received from fw are valid or not
* @igtk_mic_fail_cnt: MIC failure count of management packets using IGTK
* @igtk_replay_cnt: Replay detection count of management packets using IGTK
* @bcn_mic_fail_cnt: MIC failure count of beacon packets using BIGTK
* @bcn_replay_cnt: Replay detection count of beacon packets using BIGTK
*/
struct pmf_bcn_protect_stats {
bool pmf_bcn_stats_valid;
uint32_t igtk_mic_fail_cnt;
uint32_t igtk_replay_cnt;
uint32_t bcn_mic_fail_cnt;
uint32_t bcn_replay_cnt;
};
/**
* struct vdev_mc_cp_stats - vdev specific stats
* @cca: cca stats
* @tx_rate_flags: tx rate flags (enum tx_rate_info)
* @chain_rssi: chain rssi
* @vdev_summary_stats: vdev's summary stats
* @pmf_bcn_stats: pmf beacon protect stats
*/
struct vdev_mc_cp_stats {
struct cca_stats cca;
uint32_t tx_rate_flags;
int8_t chain_rssi[MAX_NUM_CHAINS];
struct summary_stats vdev_summary_stats;
struct pmf_bcn_protect_stats pmf_bcn_stats;
};
/**
@ -560,6 +578,7 @@ struct peer_stats_info_ext_event {
* MSB indicates if this feature is supported by FW or not.
* @num_peer_stats_info_ext: number of peer extended stats info
* @peer_stats_info_ext: peer extended stats info
* @pmf_bcn_protect_stats: pmf bcn protect stats
*/
struct stats_event {
uint32_t num_pdev_stats;
@ -585,6 +604,7 @@ struct stats_event {
uint32_t last_event;
uint32_t num_peer_stats_info_ext;
struct peer_stats_info_ext_event *peer_stats_info_ext;
struct pmf_bcn_protect_stats bcn_protect_stats;
};
/**

View File

@ -648,6 +648,48 @@ end:
wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
}
static void
tgt_mc_cp_stats_extract_pmf_bcn_stats(struct wlan_objmgr_psoc *psoc,
struct stats_event *ev)
{
QDF_STATUS status;
struct request_info last_req = {0};
struct wlan_objmgr_vdev *vdev;
struct vdev_mc_cp_stats *vdev_mc_stats;
struct vdev_cp_stats *vdev_cp_stats_priv;
status = ucfg_mc_cp_stats_get_pending_req(psoc,
TYPE_STATION_STATS,
&last_req);
if (QDF_IS_STATUS_ERROR(status)) {
cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed");
return;
}
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, last_req.vdev_id,
WLAN_CP_STATS_ID);
if (!vdev) {
cp_stats_err("vdev is null");
return;
}
vdev_cp_stats_priv = wlan_cp_stats_get_vdev_stats_obj(vdev);
if (!vdev_cp_stats_priv) {
cp_stats_err("vdev cp stats object is null");
wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
return;
}
wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv);
vdev_mc_stats = vdev_cp_stats_priv->vdev_stats;
if (ev->bcn_protect_stats.pmf_bcn_stats_valid)
vdev_mc_stats->pmf_bcn_stats = ev->bcn_protect_stats;
wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv);
wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID);
}
static void tgt_mc_cp_stats_extract_vdev_summary_stats(
struct wlan_objmgr_psoc *psoc,
struct stats_event *ev)
@ -701,6 +743,7 @@ static void tgt_mc_cp_stats_extract_vdev_summary_stats(
qdf_mem_copy(&vdev_mc_stats->vdev_summary_stats,
&ev->vdev_summary_stats[i].stats,
sizeof(vdev_mc_stats->vdev_summary_stats));
wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv);
peer = wlan_objmgr_get_peer(psoc, last_req.pdev_id,
@ -851,6 +894,8 @@ tgt_mc_cp_stats_prepare_n_send_raw_station_stats(struct wlan_objmgr_psoc *psoc,
vdev_mc_stats->chain_rssi,
sizeof(vdev_mc_stats->chain_rssi));
info.tx_rate_flags = vdev_mc_stats->tx_rate_flags;
info.bcn_protect_stats = vdev_mc_stats->pmf_bcn_stats;
wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv);
info.peer_adv_stats = qdf_mem_malloc(sizeof(*info.peer_adv_stats));
@ -907,6 +952,7 @@ static void tgt_mc_cp_stats_extract_station_stats(
tgt_mc_cp_stats_extract_peer_stats(psoc, ev, true);
tgt_mc_cp_stats_extract_vdev_summary_stats(psoc, ev);
tgt_mc_cp_stats_extract_vdev_chain_rssi_stats(psoc, ev);
tgt_mc_cp_stats_extract_pmf_bcn_stats(psoc, ev);
/*
* PEER stats are the last stats sent for get_station statistics.

View File

@ -375,6 +375,38 @@ static QDF_STATUS target_if_cp_stats_extract_pdev_stats(
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS target_if_cp_stats_extract_pmf_bcn_protect_stats(
struct wmi_unified *wmi_hdl,
wmi_host_stats_event *stats_param,
struct stats_event *ev, uint8_t *data)
{
QDF_STATUS status;
wmi_host_pmf_bcn_protect_stats pmf_bcn_stats = {0};
if (!(stats_param->stats_id & WMI_HOST_REQUEST_PMF_BCN_PROTECT_STAT))
return QDF_STATUS_SUCCESS;
qdf_mem_zero(&ev->bcn_protect_stats, sizeof(ev->bcn_protect_stats));
status = wmi_extract_pmf_bcn_protect_stats(wmi_hdl, data,
&pmf_bcn_stats);
if (QDF_IS_STATUS_ERROR(status)) {
cp_stats_err("wmi_extract_pmf_bcn_protect_stats failed");
return status;
}
ev->bcn_protect_stats.pmf_bcn_stats_valid = true;
ev->bcn_protect_stats.igtk_mic_fail_cnt =
pmf_bcn_stats.igtk_mic_fail_cnt;
ev->bcn_protect_stats.igtk_replay_cnt =
pmf_bcn_stats.igtk_replay_cnt;
ev->bcn_protect_stats.bcn_mic_fail_cnt =
pmf_bcn_stats.bcn_mic_fail_cnt;
ev->bcn_protect_stats.bcn_replay_cnt =
pmf_bcn_stats.bcn_replay_cnt;
return QDF_STATUS_SUCCESS;
}
static void target_if_cp_stats_extract_peer_extd_stats(
struct wmi_unified *wmi_hdl,
wmi_host_stats_event *stats_param,
@ -709,7 +741,7 @@ static QDF_STATUS target_if_cp_stats_extract_event(struct wmi_unified *wmi_hdl,
cp_stats_nofl_debug("num: pdev: %d, pdev_extd: %d, vdev: %d, peer: %d,"
"peer_extd: %d rssi: %d, mib %d, mib_extd %d, "
"bcnflt: %d, channel: %d, bcn: %d, peer_extd2: %d,"
"last_event: %x",
"last_event: %x, stats id: %d",
stats_param.num_pdev_stats,
stats_param.num_pdev_ext_stats,
stats_param.num_vdev_stats,
@ -721,7 +753,9 @@ static QDF_STATUS target_if_cp_stats_extract_event(struct wmi_unified *wmi_hdl,
stats_param.num_bcnflt_stats,
stats_param.num_chan_stats,
stats_param.num_bcn_stats,
stats_param.num_peer_adv_stats, stats_param.last_event);
stats_param.num_peer_adv_stats,
stats_param.last_event,
stats_param.stats_id);
ev->last_event = stats_param.last_event;
status = target_if_cp_stats_extract_pdev_stats(wmi_hdl, &stats_param,
@ -757,7 +791,11 @@ static QDF_STATUS target_if_cp_stats_extract_event(struct wmi_unified *wmi_hdl,
if (QDF_IS_STATUS_ERROR(status))
return status;
return QDF_STATUS_SUCCESS;
status = target_if_cp_stats_extract_pmf_bcn_protect_stats(wmi_hdl,
&stats_param,
ev, data);
return status;
}
/**
@ -1090,7 +1128,8 @@ static uint32_t get_stats_id(enum stats_req_type type)
WMI_REQUEST_VDEV_STAT |
WMI_REQUEST_PDEV_STAT |
WMI_REQUEST_PEER_EXTD2_STAT |
WMI_REQUEST_RSSI_PER_CHAIN_STAT);
WMI_REQUEST_RSSI_PER_CHAIN_STAT |
WMI_REQUEST_PMF_BCN_PROTECT_STAT);
case TYPE_MIB_STATS:
return (WMI_REQUEST_MIB_STAT | WMI_REQUEST_MIB_EXTD_STAT);
}

View File

@ -700,6 +700,7 @@ struct hdd_stats {
#endif
struct hdd_eapol_stats_s hdd_eapol_stats;
struct hdd_dhcp_stats_s hdd_dhcp_stats;
struct pmf_bcn_protect_stats bcn_protect_stats;
};
/**

View File

@ -58,6 +58,19 @@
#define STATION_MAX \
QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
#define STA_INFO_INVALID \
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_INVALID
#define STA_INFO_BIP_MIC_ERROR_COUNT \
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_MIC_ERROR_COUNT
#define STA_INFO_BIP_REPLAY_COUNT \
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_REPLAY_COUNT
#define STA_INFO_BEACON_MIC_ERROR_COUNT \
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_MIC_ERROR_COUNT
#define STA_INFO_BEACON_REPLAY_COUNT \
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_REPLAY_COUNT
#define STA_INFO_MAX \
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX
/* define short names for get station info attributes */
#define LINK_INFO_STANDARD_NL80211_ATTR \
QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_LINK_STANDARD_NL80211_ATTR
@ -127,7 +140,6 @@
*/
#define HDD_STATION_INFO_RX_MC_BC_COUNT (1 << 31)
const struct nla_policy
hdd_get_station_policy[STATION_MAX + 1] = {
[STATION_INFO] = {.type = NLA_FLAG},
@ -1593,6 +1605,55 @@ hdd_add_peer_stats_get_len(struct hdd_station_info *stainfo)
nla_attr_size(sizeof(stainfo->tx_retry_exhaust_fw)));
}
/**
* hdd_get_pmf_bcn_protect_stats_len() - get pmf bcn protect counters len
* @adapter: adapter holding valid bcn protect counters
*
* This function calculates the data length for valid pmf bcn counters.
*
* Return: total data length used in hdd_add_peer_stats()
*/
static uint32_t
hdd_get_pmf_bcn_protect_stats_len(struct hdd_adapter *adapter)
{
if (!adapter->hdd_stats.bcn_protect_stats.pmf_bcn_stats_valid)
return 0;
/* 4 pmf becon protect counters each of 32 bit */
return nla_attr_size(sizeof(uint32_t) * 4);
}
/**
* hdd_add_pmf_bcn_protect_stats() - add pmf bcn protect counters in resp
* @skb: pointer to response skb buffer
* @adapter: adapter holding valid bcn protect counters
*
* This function adds the pmf bcn stats in response.
*
* Return: 0 on success
*/
static int hdd_add_pmf_bcn_protect_stats(struct sk_buff *skb,
struct hdd_adapter *adapter)
{
if (!adapter->hdd_stats.bcn_protect_stats.pmf_bcn_stats_valid)
return 0;
adapter->hdd_stats.bcn_protect_stats.pmf_bcn_stats_valid = 0;
if (nla_put_u32(skb, STA_INFO_BIP_MIC_ERROR_COUNT,
adapter->hdd_stats.bcn_protect_stats.igtk_mic_fail_cnt) ||
nla_put_u32(skb, STA_INFO_BIP_REPLAY_COUNT,
adapter->hdd_stats.bcn_protect_stats.igtk_replay_cnt) ||
nla_put_u32(skb, STA_INFO_BEACON_MIC_ERROR_COUNT,
adapter->hdd_stats.bcn_protect_stats.bcn_mic_fail_cnt) ||
nla_put_u32(skb, STA_INFO_BEACON_REPLAY_COUNT,
adapter->hdd_stats.bcn_protect_stats.bcn_replay_cnt)) {
hdd_err("put fail");
return -EINVAL;
}
return 0;
}
/**
* hdd_add_peer_stats - add peer statistics information
* @skb: pointer to response skb buffer
@ -1807,6 +1868,49 @@ static int hdd_get_station_remote_ex(struct hdd_context *hdd_ctx,
return hdd_get_connected_station_info_ex(hdd_ctx, adapter, stainfo);
}
/**
* hdd_get_station_info_ex() - send STA info to userspace, for STA mode only
* @hdd_ctx: pointer to hdd context
* @adapter: pointer to adapter
*
* Return: 0 if success else error status
*/
static int hdd_get_station_info_ex(struct hdd_context *hdd_ctx,
struct hdd_adapter *adapter)
{
struct sk_buff *skb;
uint32_t nl_buf_len;
struct hdd_station_ctx *hdd_sta_ctx;
hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
if (wlan_hdd_get_station_stats(adapter)) {
hdd_err_rl("wlan_hdd_get_station_stats fail");
return -EINVAL;
}
nl_buf_len = hdd_get_pmf_bcn_protect_stats_len(adapter);
if (!nl_buf_len) {
hdd_err_rl("Failed to get bcn pmf stats");
return -EINVAL;
}
nl_buf_len += NLMSG_HDRLEN;
skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
if (!skb) {
hdd_err_rl("cfg80211_vendor_cmd_alloc_reply_skb failed");
return -ENOMEM;
}
if (hdd_add_pmf_bcn_protect_stats(skb, adapter)) {
hdd_err_rl("hdd_add_pmf_bcn_protect_stats fail");
kfree_skb(skb);
return -EINVAL;
}
return cfg80211_vendor_cmd_reply(skb);
}
/**
* __hdd_cfg80211_get_sta_info_cmd() - Handle get sta info vendor cmd
* @wiphy: pointer to wireless phy
@ -1857,6 +1961,7 @@ __hdd_cfg80211_get_sta_info_cmd(struct wiphy *wiphy,
switch (adapter->device_mode) {
case QDF_STA_MODE:
case QDF_P2P_CLIENT_MODE:
status = hdd_get_station_info_ex(hdd_ctx, adapter);
break;
case QDF_SAP_MODE:
case QDF_P2P_GO_MODE:

View File

@ -30,7 +30,7 @@ extern const struct nla_policy hdd_get_station_policy[
QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
/**
* wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
* hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
* @wiphy: corestack handler
* @wdev: wireless device
* @data: data
@ -50,14 +50,14 @@ extern const struct nla_policy hdd_get_sta_policy[
QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX + 1];
/**
* wlan_hdd_cfg80211_get_sta_info_cmd() - Handle get sta info vendor cmd
* hdd_cfg80211_get_sta_info_cmd() - Handle get sta info vendor cmd
* @wiphy: corestack handler
* @wdev: wireless device
* @data: data
* @data_len: data length
*
* Handles QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO.
* Validate cmd attributes and send the station info to upper layers.
* Validate cmd attributes and send the sta info to upper layers.
*
* Return: Success(0) or reason code for failure
*/

View File

@ -4866,15 +4866,12 @@ void hdd_wlan_fill_per_chain_rssi_stats(struct station_info *sinfo,
sinfo->filled |= HDD_INFO_SIGNAL_AVG;
}
}
#else
static inline
void hdd_wlan_fill_per_chain_rssi_stats(struct station_info *sinfo,
struct hdd_adapter *adapter)
{
}
#endif
#if defined(CFG80211_RX_FCS_ERROR_REPORTING_SUPPORT)
@ -6229,6 +6226,7 @@ int wlan_hdd_get_station_stats(struct hdd_adapter *adapter)
qdf_mem_copy(adapter->hdd_stats.per_chain_rssi_stats.rssi,
stats->vdev_chain_rssi[0].chain_rssi,
sizeof(stats->vdev_chain_rssi[0].chain_rssi));
adapter->hdd_stats.bcn_protect_stats = stats->bcn_protect_stats;
wlan_cfg80211_mc_cp_stats_free_stats_event(stats);
out:

View File

@ -495,6 +495,7 @@ static void get_station_stats_cb(struct stats_event *ev, void *cookie)
qdf_mem_copy(priv->vdev_chain_rssi, ev->vdev_chain_rssi, rssi_size);
qdf_mem_copy(priv->vdev_summary_stats, ev->vdev_summary_stats,
summary_size);
priv->bcn_protect_stats = ev->bcn_protect_stats;
station_stats_cb_fail:
osif_request_complete(request);
@ -585,6 +586,7 @@ wlan_cfg80211_mc_cp_stats_get_station_stats(struct wlan_objmgr_vdev *vdev,
if (priv->peer_adv_stats)
out->peer_adv_stats = priv->peer_adv_stats;
priv->peer_adv_stats = NULL;
out->bcn_protect_stats = priv->bcn_protect_stats;
osif_request_put(request);
osif_debug("Exit");