diff options
| author | Dustin Brown <dustinb@codeaurora.org> | 2017-01-09 12:46:03 -0800 |
|---|---|---|
| committer | qcabuildsw <qcabuildsw@localhost> | 2017-01-18 02:20:55 -0800 |
| commit | aa6a64449b3c667f01bae69cf77f328f60d9fbd6 (patch) | |
| tree | 0f153140f81ce765c331361b9d6a28dce0d0a6ae | |
| parent | 597ee2178a8144fd6d9123ab51bccff548ef5b9f (diff) | |
qcacld-3.0: Add internal ioctl to get suspend/resume stats
To assist in testing scenarios, add an ioctl that prints the
suspend/resume stats since the driver was last loaded.
Change-Id: I48e60dd0420e658ea43de721e9802f999b653bd3
CRs-Fixed: 1109141
| -rw-r--r-- | core/hdd/inc/wlan_hdd_main.h | 15 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_driver_ops.c | 4 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_power.c | 52 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_wext.c | 117 |
4 files changed, 164 insertions, 24 deletions
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 241b9fd82527..356f606cdbf2 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1310,6 +1310,18 @@ enum suspend_fail_reason { SUSPEND_FAIL_MAX_COUNT }; +/** + * suspend_resume_stats - Collection of counters for suspend/resume events + * @suspends: number of suspends completed + * @resumes: number of resumes completed + * @suspend_fail: counters for failed suspend reasons + */ +struct suspend_resume_stats { + uint32_t suspends; + uint32_t resumes; + uint32_t suspend_fail[SUSPEND_FAIL_MAX_COUNT]; +}; + /** Adapter structure definition */ struct hdd_context_s { /** Global CDS context */ @@ -1587,8 +1599,7 @@ struct hdd_context_s { bool update_mac_addr_to_fw; struct acs_dfs_policy acs_policy; uint16_t wmi_max_len; - /* counters for failed suspend reasons */ - uint32_t suspend_fail_stats[SUSPEND_FAIL_MAX_COUNT]; + struct suspend_resume_stats suspend_resume_stats; struct hdd_runtime_pm_context runtime_context; bool roaming_in_progress; /* bit map to set/reset TDLS by different sources */ diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index 332bb3531005..f2e714d3fc9d 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -635,6 +635,8 @@ static int __wlan_hdd_bus_suspend_noirq(void) if (err) goto resume_hif_noirq; + hdd_ctx->suspend_resume_stats.suspends++; + hdd_info("suspend_noirq done"); return 0; diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index d31d92f74a60..3a63ba7b6e7c 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -1710,19 +1710,20 @@ static int wlan_hdd_set_powersave(hdd_adapter_t *adapter, static void wlan_hdd_print_suspend_fail_stats(hdd_context_t *hdd_ctx) { + struct suspend_resume_stats *stats = &hdd_ctx->suspend_resume_stats; hdd_err("ipa:%d, radar:%d, roam:%d, scan:%d, initial_wakeup:%d", - hdd_ctx->suspend_fail_stats[SUSPEND_FAIL_IPA], - hdd_ctx->suspend_fail_stats[SUSPEND_FAIL_RADAR], - hdd_ctx->suspend_fail_stats[SUSPEND_FAIL_ROAM], - hdd_ctx->suspend_fail_stats[SUSPEND_FAIL_SCAN], - hdd_ctx->suspend_fail_stats[SUSPEND_FAIL_INITIAL_WAKEUP]); + stats->suspend_fail[SUSPEND_FAIL_IPA], + stats->suspend_fail[SUSPEND_FAIL_RADAR], + stats->suspend_fail[SUSPEND_FAIL_ROAM], + stats->suspend_fail[SUSPEND_FAIL_SCAN], + stats->suspend_fail[SUSPEND_FAIL_INITIAL_WAKEUP]); } void wlan_hdd_inc_suspend_stats(hdd_context_t *hdd_ctx, enum suspend_fail_reason reason) { wlan_hdd_print_suspend_fail_stats(hdd_ctx); - hdd_ctx->suspend_fail_stats[reason]++; + hdd_ctx->suspend_resume_stats.suspend_fail[reason]++; wlan_hdd_print_suspend_fail_stats(hdd_ctx); } @@ -1741,30 +1742,38 @@ static int __wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy) hdd_adapter_t *pAdapter; hdd_adapter_list_node_t *pAdapterNode, *pNext; QDF_STATUS status = QDF_STATUS_SUCCESS; - int result; + int exit_code; p_cds_sched_context cds_sched_context = get_cds_sched_ctxt(); ENTER(); - if (cds_is_driver_recovering()) - return 0; + if (cds_is_driver_recovering()) { + hdd_info("Driver is recovering; Skipping resume"); + exit_code = 0; + goto exit_with_code; + } if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_err("Command not allowed in FTM mode"); - return -EINVAL; + exit_code = -EINVAL; + goto exit_with_code; } - result = wlan_hdd_validate_context(pHddCtx); - if (0 != result) - return result; + exit_code = wlan_hdd_validate_context(pHddCtx); + if (exit_code) { + hdd_err("Invalid HDD context"); + goto exit_with_code; + } mutex_lock(&pHddCtx->iface_change_lock); if (pHddCtx->driver_status != DRIVER_MODULES_ENABLED) { mutex_unlock(&pHddCtx->iface_change_lock); - hdd_info("Driver Module not enabled return success"); - return 0; + hdd_info("Driver is not enabled; Skipping resume"); + exit_code = 0; + goto exit_with_code; } mutex_unlock(&pHddCtx->iface_change_lock); + pld_request_bus_bandwidth(pHddCtx->parent_dev, PLD_BUS_WIDTH_MEDIUM); /* Resume MC thread */ @@ -1789,14 +1798,13 @@ static int __wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy) if (true != pHddCtx->isSchedScanUpdatePending) { qdf_spin_unlock(&pHddCtx->sched_scan_lock); hdd_info("Return resume is not due to PNO indication"); - return 0; + goto exit_with_success; } /* Reset flag to avoid updatating cfg80211 data old results again */ pHddCtx->isSchedScanUpdatePending = false; qdf_spin_unlock(&pHddCtx->sched_scan_lock); status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); - while (NULL != pAdapterNode && QDF_STATUS_SUCCESS == status) { pAdapter = pAdapterNode->pAdapter; if ((NULL != pAdapter) && @@ -1819,15 +1827,19 @@ static int __wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy) } hdd_info("cfg80211 scan result database updated"); - EXIT(); - return result; + goto exit_with_success; } status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); pAdapterNode = pNext; } +exit_with_success: + pHddCtx->suspend_resume_stats.resumes++; + exit_code = 0; + +exit_with_code: EXIT(); - return result; + return exit_code; } /** diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index c46b8d8c79a6..9d642dfddb0b 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -408,6 +408,29 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { #define WE_GET_WMM_STATUS 4 #define WE_GET_CHANNEL_LIST 5 #define WE_GET_RSSI 6 + +/* + * <ioctl> + * getSuspendStats - Get suspend/resume stats + * + * @INPUT: None + * + * @OUTPUT: character string containing formatted suspend/resume stats + * + * This ioctl is used to get suspend/resume stats formatted for display. + * Currently it includes suspend/resume counts, wow wake up reasons, and + * suspend fail reasons. + * + * @E.g: iwpriv wlan0 getSuspendStats + * iwpriv wlan0 getSuspendStats + * + * Supported Feature: suspend/resume + * + * Usage: Internal + * + * </ioctl> + */ +#define WE_GET_SUSPEND_RESUME_STATS 7 #ifdef FEATURE_WLAN_TDLS /* * <ioctl> @@ -1293,6 +1316,81 @@ void hdd_wlan_get_stats(hdd_adapter_t *pAdapter, uint16_t *length, } /** + * wlan_hdd_write_suspend_resume_stats() - Writes suspend/resume stats to buffer + * @hdd_ctx: The Hdd context owning the stats to be written + * @buffer: The char buffer to write to + * @max_len: The maximum number of chars to write + * + * This assumes hdd_ctx has already been validated, and buffer is not NULL. + * + * Return - length of written content, negative number on error + */ +static int wlan_hdd_write_suspend_resume_stats(hdd_context_t *hdd_ctx, + char *buffer, uint16_t max_len) +{ + QDF_STATUS status; + struct suspend_resume_stats *sr_stats; + struct sir_wake_lock_stats wow_stats; + + sr_stats = &hdd_ctx->suspend_resume_stats; + + status = wma_get_wakelock_stats(&wow_stats); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("Failed to get WoW stats"); + return qdf_status_to_os_return(status); + } + + return scnprintf(buffer, max_len, + "\n" + "Suspends: %u\n" + "Resumes: %u\n" + "\n" + "Suspend Fail Reasons\n" + "\tIPA: %u\n" + "\tRadar: %u\n" + "\tRoam: %u\n" + "\tScan: %u\n" + "\tInitial Wakeup: %u\n" + "\n" + "WoW Wake Reasons\n" + "\tunicast: %u\n" + "\tbroadcast: %u\n" + "\tIPv4 multicast: %u\n" + "\tIPv6 multicast: %u\n" + "\tIPv6 multicast RA: %u\n" + "\tIPv6 multicast NS: %u\n" + "\tIPv6 multicast NA: %u\n" + "\tICMPv4: %u\n" + "\tICMPv6: %u\n" + "\tRSSI Breach: %u\n" + "\tLow RSSI: %u\n" + "\tG-Scan: %u\n" + "\tPNO Complete: %u\n" + "\tPNO Match: %u\n", + sr_stats->suspends, + sr_stats->resumes, + sr_stats->suspend_fail[SUSPEND_FAIL_IPA], + sr_stats->suspend_fail[SUSPEND_FAIL_RADAR], + sr_stats->suspend_fail[SUSPEND_FAIL_ROAM], + sr_stats->suspend_fail[SUSPEND_FAIL_SCAN], + sr_stats->suspend_fail[SUSPEND_FAIL_INITIAL_WAKEUP], + wow_stats.wow_ucast_wake_up_count, + wow_stats.wow_bcast_wake_up_count, + wow_stats.wow_ipv4_mcast_wake_up_count, + wow_stats.wow_ipv6_mcast_wake_up_count, + wow_stats.wow_ipv6_mcast_ra_stats, + wow_stats.wow_ipv6_mcast_ns_stats, + wow_stats.wow_ipv6_mcast_na_stats, + wow_stats.wow_icmpv4_count, + wow_stats.wow_icmpv6_count, + wow_stats.wow_rssi_breach_wake_up_count, + wow_stats.wow_low_rssi_wake_up_count, + wow_stats.wow_gscan_wake_up_count, + wow_stats.wow_pno_complete_wake_up_count, + wow_stats.wow_pno_match_wake_up_count); +} + +/** * hdd_wlan_list_fw_profile() - Get fw profiling points * @length: Size of the data copied * @buffer: Pointer to char buffer. @@ -7871,6 +7969,18 @@ static int __iw_get_char_setnone(struct net_device *dev, break; } + case WE_GET_SUSPEND_RESUME_STATS: + { + ret = wlan_hdd_write_suspend_resume_stats(hdd_ctx, extra, + WE_MAX_STR_LEN); + if (ret >= 0) { + wrqu->data.length = ret; + ret = 0; + } + + break; + } + case WE_LIST_FW_PROFILE: hdd_wlan_list_fw_profile(&(wrqu->data.length), extra, WE_MAX_STR_LEN); @@ -8338,8 +8448,9 @@ static int __iw_get_char_setnone(struct net_device *dev, break; } } + EXIT(); - return 0; + return ret; } static int iw_get_char_setnone(struct net_device *dev, @@ -11741,6 +11852,10 @@ static const struct iw_priv_args we_private_args[] = { 0, IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, "getStats"}, + {WE_GET_SUSPEND_RESUME_STATS, + 0, + IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, + "getSuspendStats"}, {WE_LIST_FW_PROFILE, 0, IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, |
