summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhang Qian <zhangq@codeaurora.org>2016-12-23 11:10:48 +0800
committerSandeep Puligilla <spuligil@codeaurora.org>2017-03-10 20:26:54 -0800
commit6db9889fbd58afb4e12a8ab387aa8b130d42b41b (patch)
tree8aff69242e75b993e9ea4b807c70db5ab4a9d174
parent8553db2fcd1bc895e9f210f7cae5031e1a12c801 (diff)
qcacld-3.0: Add peer ps change and TX failure indication
qcacld-2.0 to qcacld-3.0 propagation This change indicates Peer STA's power state change and TX failure to NL80211. Vendor command QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT(127) is introduced by this change. Change-Id: Iaa1c14e5cdc5a7d04beebbff1149daf871f9ef5a CRs-fixed: 1048388
-rw-r--r--core/hdd/src/wlan_hdd_cfg80211.c6
-rw-r--r--core/hdd/src/wlan_hdd_cfg80211.h56
-rw-r--r--core/hdd/src/wlan_hdd_main.c3
-rw-r--r--core/hdd/src/wlan_hdd_stats.c200
-rw-r--r--core/hdd/src/wlan_hdd_stats.h14
5 files changed, 279 insertions, 0 deletions
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index 5f965c9b388d..2f3a7f9834b3 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -963,6 +963,12 @@ static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] =
.subcmd =
QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
},
+ [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
+ .vendor_id =
+ QCA_NL80211_VENDOR_ID,
+ .subcmd =
+ QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
+ },
#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
[QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
.vendor_id =
diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h
index c739edf352c5..c667d9b41db7 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.h
+++ b/core/hdd/src/wlan_hdd_cfg80211.h
@@ -295,6 +295,8 @@ typedef enum {
* indicated through an event using the same sub command through
* @QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_STATUS. Attributes are
* listed in qca_wlan_vendor_attr_sap_conditional_chan_switch
+ * @QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT: Command/event used to config
+ * indication period and threshold for MAC layer counters.
* @QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS: Configure the TDLS behavior
* in the host driver. The different TDLS configurations are defined
* by the attributes in enum qca_wlan_vendor_attr_tdls_configuration.
@@ -445,6 +447,8 @@ enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP = 123,
QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH = 124,
+ QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT = 127,
+
/* Encrypt/Decrypt command */
QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST = 137,
@@ -640,6 +644,7 @@ enum qca_wlan_vendor_attr_get_station_info {
* @QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX: Radio stats
* @QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX: Iface stats
* @QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX: Peer info stats
+ * @QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX: MAC layer counters
* @QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX: Ext tdls state change
* @QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX: ACS command
* @QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX: Pass Roam and Auth info
@@ -698,6 +703,7 @@ enum qca_nl80211_vendor_subcmds_index {
QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX,
QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX,
QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX,
+ QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX,
#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX,
@@ -3288,6 +3294,56 @@ enum qca_vendor_attr_sar_limits {
QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_AFTER_LAST - 1
};
+/**
+ * enum qca_wlan_vendor_attr_ll_stats_ext - Attributes for MAC layer monitoring
+ * offload which is an extension for LL_STATS.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CFG_PERIOD: Monitoring period. Unit in ms.
+ * If MAC counters do not exceed the threshold, FW will report monitored
+ * link layer counters periodically as this setting. The first report is
+ * always triggered by this timer.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CFG_THRESHOLD: It is a percentage(1 ~ 99).
+ * For each MAC layer counter, FW holds two copies. One is the current value.
+ * The other is the last report. Once a current counter's increment is larger
+ * than the theshold, FW will indicate that counter to host even the
+ * monitoring timer does not expire.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_MAC_ADDRESS: Peer sta's MAC address
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_CHG: Peer sta power state change
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_STATE: Current power state of
+ * peer STA.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TID: TID of msdu
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_NUM_MSDU: Count of msdu with the same
+ * failure code.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_STATUS: TX failure code
+ * 1: TX packet discarded
+ * 2: No ACK
+ * 3: Postpone
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_MAC_ADDRESS: peer MAC address
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_STATE: Peer STA current state
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_NUM: number of peers
+*/
+enum qca_wlan_vendor_attr_ll_stats_ext {
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_INVALID = 0,
+
+ /* Attributes for configurations */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CFG_PERIOD,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CFG_THRESHOLD,
+
+ /* Peer STA power state change */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_CHG,
+
+ /* TX failure event */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TID,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_NUM_MSDU,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_STATUS,
+
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_STATE,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_MAC_ADDRESS,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_NUM,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_LAST,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_MAX =
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_LAST - 1
+};
+
struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
tCsrRoamInfo *pRoamInfo);
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index ce37736fad9d..69d33a7d6cb7 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -8837,6 +8837,9 @@ int hdd_register_cb(hdd_context_t *hdd_ctx)
sme_rso_cmd_status_cb(hdd_ctx->hHal, wlan_hdd_rso_cmd_status_cb);
+ sme_set_link_layer_ext_cb(hdd_ctx->hHal,
+ wlan_hdd_cfg80211_link_layer_stats_ext_callback);
+
status = sme_set_lost_link_info_cb(hdd_ctx->hHal,
hdd_lost_link_info_cb);
/* print error and not block the startup process */
diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c
index 90aaaa3b3126..3b8e483c85ce 100644
--- a/core/hdd/src/wlan_hdd_stats.c
+++ b/core/hdd/src/wlan_hdd_stats.c
@@ -1572,6 +1572,206 @@ int wlan_hdd_cfg80211_ll_stats_clear(struct wiphy *wiphy,
return ret;
}
+/**
+ * hdd_populate_per_peer_ps_info() - populate per peer sta's PS info
+ * @wifi_peer_info: peer information
+ * @vendor_event: buffer for vendor event
+ *
+ * Return: 0 success
+ */
+static inline int
+hdd_populate_per_peer_ps_info(tSirWifiPeerInfo *wifi_peer_info,
+ struct sk_buff *vendor_event)
+{
+ if (!wifi_peer_info) {
+ hdd_err("Invalid pointer to peer info.");
+ return -EINVAL;
+ }
+
+ if (nla_put_u32(vendor_event,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_STATE,
+ wifi_peer_info->power_saving) ||
+ nla_put(vendor_event,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_MAC_ADDRESS,
+ QDF_MAC_ADDR_SIZE, &wifi_peer_info->peerMacAddress)) {
+ hdd_err("QCA_WLAN_VENDOR_ATTR put fail.");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/**
+ * hdd_populate_wifi_peer_ps_info() - populate peer sta's power state
+ * @data: stats for peer STA
+ * @vendor_event: buffer for vendor event
+ *
+ * Return: 0 success
+ */
+static int hdd_populate_wifi_peer_ps_info(tSirWifiPeerStat *data,
+ struct sk_buff *vendor_event)
+{
+ uint32_t peer_num, i;
+ tSirWifiPeerInfo *wifi_peer_info;
+ struct nlattr *peer_info, *peers;
+
+ if (!data) {
+ hdd_err("Invalid pointer to Wifi peer stat.");
+ return -EINVAL;
+ }
+
+ peer_num = data->numPeers;
+ if (peer_num == 0) {
+ hdd_err("Peer number is zero.");
+ return -EINVAL;
+ }
+
+ if (nla_put_u32(vendor_event,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_NUM,
+ peer_num)) {
+ hdd_err("QCA_WLAN_VENDOR_ATTR put fail");
+ return -EINVAL;
+ }
+
+ peer_info = nla_nest_start(vendor_event,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_CHG);
+ if (peer_info == NULL) {
+ hdd_err("nla_nest_start failed");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < peer_num; i++) {
+ wifi_peer_info = &data->peerInfo[i];
+ peers = nla_nest_start(vendor_event, i);
+
+ if (hdd_populate_per_peer_ps_info(wifi_peer_info,
+ vendor_event))
+ return -EINVAL;
+
+ nla_nest_end(vendor_event, peers);
+ }
+ nla_nest_end(vendor_event, peer_info);
+
+ return 0;
+}
+
+/**
+ * hdd_populate_tx_failure_info() - populate TX failure info
+ * @tx_fail: TX failure info
+ * @skb: buffer for vendor event
+ *
+ * Return: 0 Success
+ */
+static inline int
+hdd_populate_tx_failure_info(struct sir_wifi_iface_tx_fail *tx_fail,
+ struct sk_buff *skb)
+{
+ int status = 0;
+
+ if (tx_fail == NULL || skb == NULL)
+ return -EINVAL;
+
+ if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TID,
+ tx_fail->tid) ||
+ nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_NUM_MSDU,
+ tx_fail->msdu_num) ||
+ nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_STATUS,
+ tx_fail->status)) {
+ hdd_err("QCA_WLAN_VENDOR_ATTR put fail");
+ status = -EINVAL;
+ }
+
+ return status;
+}
+
+/**
+ * wlan_hdd_cfg80211_link_layer_stats_ext_callback() - Callback for LL ext
+ * @ctx: HDD context
+ * @rsp: msg from FW
+ *
+ * This function is an extension of
+ * wlan_hdd_cfg80211_link_layer_stats_callback. It converts
+ * monitoring parameters offloaded to NL data and send the same to the
+ * kernel/upper layers.
+ *
+ * Return: None
+ */
+void wlan_hdd_cfg80211_link_layer_stats_ext_callback(tHddHandle ctx,
+ tSirLLStatsResults *rsp)
+{
+ hdd_context_t *hdd_ctx;
+ struct sk_buff *skb = NULL;
+ uint32_t param_id, index;
+ hdd_adapter_t *adapter = NULL;
+ tSirLLStatsResults *linkLayer_stats_results;
+ tSirWifiPeerStat *peer_stats;
+ uint8_t *results;
+ int status;
+
+ ENTER();
+
+ if (!ctx) {
+ hdd_err("Invalid HDD context.");
+ return;
+ }
+
+ if (!rsp) {
+ hdd_err("Invalid result.");
+ return;
+ }
+
+ hdd_ctx = (hdd_context_t *)ctx;
+ linkLayer_stats_results = (tSirLLStatsResults *)rsp;
+
+ status = wlan_hdd_validate_context(hdd_ctx);
+ if (0 != status)
+ return;
+
+ adapter = hdd_get_adapter_by_vdev(hdd_ctx,
+ linkLayer_stats_results->ifaceId);
+
+ if (NULL == adapter) {
+ hdd_err("vdev_id %d does not exist with host.",
+ linkLayer_stats_results->ifaceId);
+ return;
+ }
+
+ index = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX;
+ skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
+ NULL, LL_STATS_EVENT_BUF_SIZE + NLMSG_HDRLEN,
+ index, GFP_KERNEL);
+ if (!skb) {
+ hdd_err("cfg80211_vendor_event_alloc failed.");
+ goto exit;
+ }
+
+ results = linkLayer_stats_results->results;
+ param_id = linkLayer_stats_results->paramId;
+ hdd_info("LL_STATS RESP paramID = 0x%x, ifaceId = %u, result = %p",
+ linkLayer_stats_results->paramId,
+ linkLayer_stats_results->ifaceId,
+ linkLayer_stats_results->results);
+ if (param_id & WMI_LL_STATS_EXT_PS_CHG) {
+ peer_stats = (tSirWifiPeerStat *)results;
+ status = hdd_populate_wifi_peer_ps_info(peer_stats, skb);
+ } else if (param_id & WMI_LL_STATS_EXT_TX_FAIL) {
+ struct sir_wifi_iface_tx_fail *tx_fail;
+
+ tx_fail = (struct sir_wifi_iface_tx_fail *)results;
+ status = hdd_populate_tx_failure_info(tx_fail, skb);
+ } else if (param_id & WMI_LL_STATS_EXT_MAC_COUNTER) {
+ hdd_info("MAC counters stats");
+ } else {
+ hdd_info("Unknown link layer stats");
+ }
+
+exit:
+ if (status == 0)
+ cfg80211_vendor_event(skb, GFP_KERNEL);
+ else
+ kfree_skb(skb);
+ EXIT();
+}
+
#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
#ifdef WLAN_FEATURE_STATS_EXT
diff --git a/core/hdd/src/wlan_hdd_stats.h b/core/hdd/src/wlan_hdd_stats.h
index 7b9bba501796..8465041ad8d5 100644
--- a/core/hdd/src/wlan_hdd_stats.h
+++ b/core/hdd/src/wlan_hdd_stats.h
@@ -238,5 +238,19 @@ int wlan_hdd_get_rcpi(hdd_adapter_t *adapter, uint8_t *mac,
int32_t *rcpi_value,
enum rcpi_measurement_type measurement_type);
+/**
+ * wlan_hdd_cfg80211_link_layer_stats_ext_callback() - Callback for LL ext
+ * @ctx: HDD context
+ * @rsp: msg from FW
+ *
+ * This function is an extension of
+ * wlan_hdd_cfg80211_link_layer_stats_callback. It converts
+ * monitoring parameters offloaded to NL data and send the same to the
+ * kernel/upper layers.
+ *
+ * Return: None.
+ */
+void wlan_hdd_cfg80211_link_layer_stats_ext_callback(tHddHandle ctx,
+ tSirLLStatsResults *rsp);
#endif /* end #if !defined(WLAN_HDD_STATS_H) */