diff options
| author | Padma, Santhosh Kumar <skpadma@codeaurora.org> | 2016-08-08 19:07:06 +0530 |
|---|---|---|
| committer | qcabuildsw <qcabuildsw@localhost> | 2016-08-19 16:58:18 -0700 |
| commit | 5e33bebbc2d4f0cb41cf47119a7306dc35108a95 (patch) | |
| tree | 8f272a7a4f7ecc753d56d54139ace870eda28c81 | |
| parent | 068c4b0fc35d8939d76ecbbf3c34f25290ad9235 (diff) | |
qcacld-3.0: Get wakelock stats
qcacld-2.0 to qcacld-3.0 propagation
Send wakelock stats to HAL layer when it requests through vendor
command QCA_NL80211_VENDOR_SUBCMD_WAKELOCK_STATS. This is a
blocking request in HDD.
Change-Id: Ie043323d90f63c19de2da9d1b8b54bc28d2c8f3d
CRs-Fixed: 958964
| -rw-r--r-- | core/hdd/src/wlan_hdd_cfg80211.c | 230 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_cfg80211.h | 63 | ||||
| -rw-r--r-- | core/mac/inc/sir_api.h | 20 | ||||
| -rw-r--r-- | core/wma/inc/wma_api.h | 1 | ||||
| -rw-r--r-- | core/wma/src/wma_features.c | 42 |
5 files changed, 356 insertions, 0 deletions
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 5bcf100a23c2..b6ec705992ef 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -6819,6 +6819,228 @@ static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy, #undef BPF_CURRENT_OFFSET #undef BPF_PROGRAM #undef BPF_MAX + +/** + * define short names for the global vendor params + * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback() + */ +#define PARAM_TOTAL_CMD_EVENT_WAKE \ + QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE +#define PARAM_CMD_EVENT_WAKE_CNT_PTR \ + QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR +#define PARAM_CMD_EVENT_WAKE_CNT_SZ \ + QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ +#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \ + QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE +#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \ + QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR +#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \ + QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ +#define PARAM_TOTAL_RX_DATA_WAKE \ + QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE +#define PARAM_RX_UNICAST_CNT \ + QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT +#define PARAM_RX_MULTICAST_CNT \ + QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT +#define PARAM_RX_BROADCAST_CNT \ + QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT +#define PARAM_ICMP_PKT \ + QCA_WLAN_VENDOR_ATTR_ICMP_PKT +#define PARAM_ICMP6_PKT \ + QCA_WLAN_VENDOR_ATTR_ICMP6_PKT +#define PARAM_ICMP6_RA \ + QCA_WLAN_VENDOR_ATTR_ICMP6_RA +#define PARAM_ICMP6_NA \ + QCA_WLAN_VENDOR_ATTR_ICMP6_NA +#define PARAM_ICMP6_NS \ + QCA_WLAN_VENDOR_ATTR_ICMP6_NS +#define PARAM_ICMP4_RX_MULTICAST_CNT \ + QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT +#define PARAM_ICMP6_RX_MULTICAST_CNT \ + QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT +#define PARAM_OTHER_RX_MULTICAST_CNT \ + QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT + + +/** + * hdd_send_wakelock_stats() - API to send wakelock stats + * @ctx: context to be passed to callback + * @data: data passed to callback + * + * This function is used to send wake lock stats to HAL layer + * + * Return: 0 on success, error number otherwise. + */ +static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx, + const struct sir_wake_lock_stats *data) +{ + struct sk_buff *skb; + uint32_t nl_buf_len; + uint32_t total_rx_data_wake, rx_multicast_cnt; + uint32_t ipv6_rx_multicast_addr_cnt; + + ENTER(); + + nl_buf_len = NLMSG_HDRLEN; + nl_buf_len += + QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX * + (NLMSG_HDRLEN + sizeof(uint32_t)); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len); + + if (!skb) { + hdd_log(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed")); + return -ENOMEM; + } + + hdd_log(LOG1, "wow_ucast_wake_up_count %d", + data->wow_ucast_wake_up_count); + hdd_log(LOG1, "wow_bcast_wake_up_count %d", + data->wow_bcast_wake_up_count); + hdd_log(LOG1, "wow_ipv4_mcast_wake_up_count %d", + data->wow_ipv4_mcast_wake_up_count); + hdd_log(LOG1, "wow_ipv6_mcast_wake_up_count %d", + data->wow_ipv6_mcast_wake_up_count); + hdd_log(LOG1, "wow_ipv6_mcast_ra_stats %d", + data->wow_ipv6_mcast_ra_stats); + hdd_log(LOG1, "wow_ipv6_mcast_ns_stats %d", + data->wow_ipv6_mcast_ns_stats); + hdd_log(LOG1, "wow_ipv6_mcast_na_stats %d", + data->wow_ipv6_mcast_na_stats); + + ipv6_rx_multicast_addr_cnt = + data->wow_ipv6_mcast_wake_up_count + + data->wow_ipv6_mcast_ra_stats + + data->wow_ipv6_mcast_ns_stats + + data->wow_ipv6_mcast_na_stats; + + rx_multicast_cnt = + data->wow_ipv4_mcast_wake_up_count + + ipv6_rx_multicast_addr_cnt; + + total_rx_data_wake = + data->wow_ucast_wake_up_count + + data->wow_bcast_wake_up_count + + rx_multicast_cnt; + + if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) || + nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) || + nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) || + nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) || + nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) || + nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) || + nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE, + total_rx_data_wake) || + nla_put_u32(skb, PARAM_RX_UNICAST_CNT, + data->wow_ucast_wake_up_count) || + nla_put_u32(skb, PARAM_RX_MULTICAST_CNT, + rx_multicast_cnt) || + nla_put_u32(skb, PARAM_RX_BROADCAST_CNT, + data->wow_bcast_wake_up_count) || + nla_put_u32(skb, PARAM_ICMP6_RA, + data->wow_ipv6_mcast_ra_stats) || + nla_put_u32(skb, PARAM_ICMP6_NA, + data->wow_ipv6_mcast_na_stats) || + nla_put_u32(skb, PARAM_ICMP6_NS, + data->wow_ipv6_mcast_ns_stats) || + nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT, + data->wow_ipv4_mcast_wake_up_count) || + nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT, + ipv6_rx_multicast_addr_cnt) || + nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0)) { + hdd_log(LOGE, FL("nla put fail")); + goto nla_put_failure; + } + + cfg80211_vendor_cmd_reply(skb); + + EXIT(); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -EINVAL; +} + +/** + * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats + * @wiphy: wiphy pointer + * @wdev: pointer to struct wireless_dev + * @data: pointer to incoming NL vendor data + * @data_len: length of @data + * + * This function parses the incoming NL vendor command data attributes and + * invokes the SME Api and blocks on a completion variable. + * WMA copies required data and invokes callback + * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats. + * + * Return: 0 on success; error number otherwise. + */ +static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + int status, ret; + struct sir_wake_lock_stats wake_lock_stats; + QDF_STATUS qdf_status; + + ENTER(); + + if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { + hdd_log(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) + return -EINVAL; + + qdf_status = wma_get_wakelock_stats(&wake_lock_stats); + if (qdf_status != QDF_STATUS_SUCCESS) { + hdd_log(LOGE, + FL("failed to get wakelock stats(err=%d)"), qdf_status); + return -EINVAL; + } + + ret = hdd_send_wakelock_stats(hdd_ctx, + &wake_lock_stats); + if (ret) + hdd_log(LOGE, FL("Failed to post wake lock stats")); + + EXIT(); + return ret; +} + +/** + * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats + * @wiphy: wiphy pointer + * @wdev: pointer to struct wireless_dev + * @data: pointer to incoming NL vendor data + * @data_len: length of @data + * + * This function parses the incoming NL vendor command data attributes and + * invokes the SME Api and blocks on a completion variable. + * WMA copies required data and invokes callback + * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats. + * + * Return: 0 on success; error number otherwise. + */ +static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data, + data_len); + cds_ssr_protect(__func__); + + return ret; +} + const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { { .info.vendor_id = QCA_NL80211_VENDOR_ID, @@ -7352,6 +7574,14 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { .doit = wlan_hdd_cfg80211_process_ndp_cmd }, #endif + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_get_wakelock_stats + }, }; /** diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index 1bd642d9d583..3edf6cbceda9 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -374,6 +374,9 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_NDP = 81, QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER = 83, + + QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS = 85, + /* OCB commands */ QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG = 92, QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME = 93, @@ -2421,6 +2424,66 @@ enum qca_wlan_vendor_attr_packet_filter { }; /** + * enum qca_wlan_vendor_attr_wake_stats - wake lock stats + * @QCA_WLAN_VENDOR_ATTR_GET_WAKE_STATS_INVALID: invalid + * @QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE: + * @QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR: + * @QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ: + * @QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE: + * @QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR: + * @QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ: + * @QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE: + * total rx wakeup count + * @QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT: + * Total rx unicast packet which woke up host + * @QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT: + * Total rx multicast packet which woke up host + * @QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT: + * Total rx broadcast packet which woke up host + * @QCA_WLAN_VENDOR_ATTR_ICMP_PKT: + * wake icmp packet count + * @QCA_WLAN_VENDOR_ATTR_ICMP6_PKT: + * wake icmp6 packet count + * @QCA_WLAN_VENDOR_ATTR_ICMP6_RA: + * wake icmp6 RA packet count + * @QCA_WLAN_VENDOR_ATTR_ICMP6_NA: + * wake icmp6 NA packet count + * @QCA_WLAN_VENDOR_ATTR_ICMP6_NS: + * wake icmp6 NS packet count + * @QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT: + * Rx wake packet count due to ipv4 multicast + * @QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT: + * Rx wake packet count due to ipv6 multicast + * @QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT: + * Rx wake packet count due to non-ipv4 and non-ipv6 packets + */ +enum qca_wlan_vendor_attr_wake_stats { + QCA_WLAN_VENDOR_ATTR_GET_WAKE_STATS_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE, + QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR, + QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ, + QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE, + QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR, + QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ, + QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE, + QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT, + QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT, + QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT, + QCA_WLAN_VENDOR_ATTR_ICMP_PKT, + QCA_WLAN_VENDOR_ATTR_ICMP6_PKT, + QCA_WLAN_VENDOR_ATTR_ICMP6_RA, + QCA_WLAN_VENDOR_ATTR_ICMP6_NA, + QCA_WLAN_VENDOR_ATTR_ICMP6_NS, + QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT, + QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT, + QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT, + /* keep last */ + QCA_WLAN_VENDOR_GET_WAKE_STATS_AFTER_LAST, + QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX = + QCA_WLAN_VENDOR_GET_WAKE_STATS_AFTER_LAST - 1, +}; + +/** * enum qca_vendor_attr_get_tsf: Vendor attributes for TSF capture * @QCA_WLAN_VENDOR_ATTR_TSF_INVALID: Invalid attribute value * @QCA_WLAN_VENDOR_ATTR_TSF_CMD: enum qca_tsf_operation (u32) diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index c4b7daf8a2cd..0a03be79b056 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -5936,6 +5936,26 @@ struct sir_bpf_get_offload { }; /** + * struct sir_wake_lock_stats - wake lock stats structure + * @wow_ucast_wake_up_count: Unicast wakeup count + * @wow_bcast_wake_up_count: Broadcast wakeup count + * @wow_ipv4_mcast_wake_up_count: ipv4 multicast wakeup count + * @wow_ipv6_mcast_wake_up_count: ipv6 multicast wakeup count + * @wow_ipv6_mcast_ra_stats: ipv6 multicast ra stats + * @wow_ipv6_mcast_ns_stats: ipv6 multicast ns stats + * @wow_ipv6_mcast_na_stats: ipv6 multicast na stats + */ +struct sir_wake_lock_stats { + uint32_t wow_ucast_wake_up_count; + uint32_t wow_bcast_wake_up_count; + uint32_t wow_ipv4_mcast_wake_up_count; + uint32_t wow_ipv6_mcast_wake_up_count; + uint32_t wow_ipv6_mcast_ra_stats; + uint32_t wow_ipv6_mcast_ns_stats; + uint32_t wow_ipv6_mcast_na_stats; +}; + +/** * enum ht_capability_fields - HT Capabilities bit fields * @HT_CAPS_LDPC: ldpc coding capability bit field * @HT_CAPS_SUPPORTED_CHANNEL_SET: channel width set bit field diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h index 00b64767a203..a80887894351 100644 --- a/core/wma/inc/wma_api.h +++ b/core/wma/inc/wma_api.h @@ -268,4 +268,5 @@ static inline QDF_STATUS wma_register_ndp_cb(QDF_STATUS (*pe_ndp_event_handler) bool wma_is_p2p_lo_capable(void); QDF_STATUS wma_p2p_lo_start(struct sir_p2p_lo_start *params); QDF_STATUS wma_p2p_lo_stop(u_int32_t vdev_id); +QDF_STATUS wma_get_wakelock_stats(struct sir_wake_lock_stats *wake_lock_stats); #endif diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 316fae5b809e..d34050c967f9 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -7905,3 +7905,45 @@ int wma_p2p_lo_event_handler(void *handle, uint8_t *event_buf, return 0; } + +/** + * wma_get_wakelock_stats() - Collects wake lock stats + * @wake_lock_stats: wakelock structure to be filled + * + * This function collects wake lock stats + * + * Return: VOS_STATUS_SUCCESS on success, error number otherwise + */ +QDF_STATUS wma_get_wakelock_stats(struct sir_wake_lock_stats *wake_lock_stats) +{ + tp_wma_handle wma_handle; + + wma_handle = cds_get_context(QDF_MODULE_ID_WMA); + + if (!wake_lock_stats) { + WMA_LOGE("%s: invalid pointer", __func__); + return QDF_STATUS_E_INVAL; + } + + if (!wma_handle) { + WMA_LOGE("%s: WMA context is invalid!", __func__); + return QDF_STATUS_E_INVAL; + } + + wake_lock_stats->wow_ucast_wake_up_count = + wma_handle->wow_ucast_wake_up_count; + wake_lock_stats->wow_bcast_wake_up_count = + wma_handle->wow_bcast_wake_up_count; + wake_lock_stats->wow_ipv4_mcast_wake_up_count = + wma_handle->wow_ipv4_mcast_wake_up_count; + wake_lock_stats->wow_ipv6_mcast_wake_up_count = + wma_handle->wow_ipv6_mcast_wake_up_count; + wake_lock_stats->wow_ipv6_mcast_ra_stats = + wma_handle->wow_ipv6_mcast_ra_stats; + wake_lock_stats->wow_ipv6_mcast_ns_stats = + wma_handle->wow_ipv6_mcast_ns_stats; + wake_lock_stats->wow_ipv6_mcast_na_stats = + wma_handle->wow_ipv6_mcast_na_stats; + + return QDF_STATUS_SUCCESS; +} |
