diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-05-09 06:21:57 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-05-09 06:21:57 +0000 |
commit | c586a6be906aa0bb64ee84a5f6b9c1197ebd8554 (patch) | |
tree | 6764eff86b364b59084567a9b1b0dc11b9a8babc | |
parent | ee17f079576bee100ecdf5b186b49b4759ecb71a (diff) | |
parent | 79464da5e668de737368f899dac7d730fb8aacc5 (diff) | |
download | wlan-c586a6be906aa0bb64ee84a5f6b9c1197ebd8554.tar.gz |
Snap for 8558685 from 79464da5e668de737368f899dac7d730fb8aacc5 to tm-frc-networking-release
Change-Id: I618244ac793b97d016930f3cf75d85578c1722f3
-rwxr-xr-x | bcmdhd/wifi_hal/Android.mk | 2 | ||||
-rwxr-xr-x | bcmdhd/wifi_hal/common.h | 46 | ||||
-rwxr-xr-x | bcmdhd/wifi_hal/cpp_bindings.cpp | 2 | ||||
-rwxr-xr-x | bcmdhd/wifi_hal/nan.cpp | 230 | ||||
-rwxr-xr-x | bcmdhd/wifi_hal/wifi_hal.cpp | 122 | ||||
-rwxr-xr-x | bcmdhd/wifi_hal/wifi_logger.cpp | 782 |
6 files changed, 1148 insertions, 36 deletions
diff --git a/bcmdhd/wifi_hal/Android.mk b/bcmdhd/wifi_hal/Android.mk index 580a730..471c312 100755 --- a/bcmdhd/wifi_hal/Android.mk +++ b/bcmdhd/wifi_hal/Android.mk @@ -45,6 +45,8 @@ ifneq ($(wildcard vendor/google/libraries/GoogleWifiConfigLib),) LOCAL_SHARED_LIBRARIES += \ google_wifi_firmware_config_version_c_wrapper LOCAL_CFLAGS += -DGOOGLE_WIFI_FW_CONFIG_VERSION_C_WRAPPER +#only for pixel feature +LOCAL_CFLAGS += -DRING_DUMP endif LOCAL_SRC_FILES := \ diff --git a/bcmdhd/wifi_hal/common.h b/bcmdhd/wifi_hal/common.h index 21f0cef..ecc1abf 100755 --- a/bcmdhd/wifi_hal/common.h +++ b/bcmdhd/wifi_hal/common.h @@ -232,7 +232,7 @@ typedef enum { WIFI_SUBCMD_OTA_UPDATE, WIFI_SUBCMD_USABLE_CHANNEL = ANDROID_NL80211_SUBCMD_USABLE_CHANNEL_START, WIFI_SUBCMD_TRIGGER_SSR = ANDROID_NL80211_SUBCMD_INIT_DEINIT_RANGE_START, - + WIFI_SUBCMD_GET_RADIO_COMBO_MATRIX, } WIFI_SUB_COMMAND; typedef enum { @@ -306,6 +306,12 @@ typedef struct { bool is_virtual; // mark each iface as virtual or static } interface_info; +typedef enum { + NAN_STATE_DISABLED = 0, + NAN_STATE_AP = 1, + NAN_STATE_CHRE = 2, +} nan_enab_state_t; + typedef struct { struct nl_sock *cmd_sock; // command socket object @@ -333,6 +339,8 @@ typedef struct { int max_num_interfaces; // max number of interfaces wifi_subsystem_restart_handler restart_handler; // trigger sub system handler + wifi_chre_handler chre_nan_cb; // chre CB for nan status + nan_enab_state_t nan_state; // Nan enable state // add other details } hal_info; @@ -448,6 +456,12 @@ wifi_error wifi_start_hal(wifi_interface_handle iface); wifi_error wifi_stop_hal(wifi_interface_handle iface); wifi_interface_handle wifi_get_wlan_interface(wifi_handle info, wifi_interface_handle *ifaceHandles, int numIfaceHandles); +#ifdef RING_DUMP +wifi_error wifi_start_ring_dump(wifi_interface_handle iface, + wifi_ring_buffer_data_handler ring_handle); +wifi_error wifi_stop_ring_dump(wifi_interface_handle iface, + wifi_ring_buffer_data_handler ring_handle); +#endif /* RING_DUMP */ wifi_error wifi_hal_ota_update(wifi_interface_handle iface, uint32_t ota_version); wifi_error wifi_hal_preInit(wifi_interface_handle iface); /* API to get wake reason statistics */ @@ -527,6 +541,36 @@ wifi_error twt_get_stats(wifi_interface_handle iface, u8 config_id, TwtStats* st wifi_error twt_clear_stats(wifi_interface_handle iface, u8 config_id); wifi_error wifi_trigger_subsystem_restart(wifi_handle handle); + +/**@brief nan_chre_enable_request + * Request from CHRE to enable NAN + * @param transaction id: + * @param wifi_interface_handle: + * @param NanEnableRequest: + * @return Synchronous wifi_error + */ +wifi_error nan_chre_enable_request(transaction_id id, + wifi_interface_handle iface, + NanEnableRequest* msg); + +/**@brief nan_chre_disable_request + * Request from CHRE to disable NAN + * @param transaction id: + * @param wifi_interface_handle: + * @return Synchronous wifi_error + */ +wifi_error nan_chre_disable_request(transaction_id id, + wifi_interface_handle iface); + +/**@brief nan_chre_register_handler + * Register chre handler to handle NAN status + * @param wifi_interface_handle: + * @param wifi_chre_handler: + * @return Synchronous wifi_error + */ +wifi_error nan_chre_register_handler(wifi_interface_handle iface, + wifi_chre_handler handler); + // some common macros #define min(x, y) ((x) < (y) ? (x) : (y)) diff --git a/bcmdhd/wifi_hal/cpp_bindings.cpp b/bcmdhd/wifi_hal/cpp_bindings.cpp index 5311e6e..7a634bd 100755 --- a/bcmdhd/wifi_hal/cpp_bindings.cpp +++ b/bcmdhd/wifi_hal/cpp_bindings.cpp @@ -647,7 +647,6 @@ int WifiCommand::requestResponse() { } int WifiCommand::requestResponse(WifiRequest& request) { - pthread_mutex_lock(&ResponseMutex); int err = 0; struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT); @@ -674,7 +673,6 @@ int WifiCommand::requestResponse(WifiRequest& request) { } out: nl_cb_put(cb); - pthread_mutex_unlock(&ResponseMutex); return mapErrorCodes(err); } diff --git a/bcmdhd/wifi_hal/nan.cpp b/bcmdhd/wifi_hal/nan.cpp index 475c697..52f29e3 100755 --- a/bcmdhd/wifi_hal/nan.cpp +++ b/bcmdhd/wifi_hal/nan.cpp @@ -290,7 +290,8 @@ typedef enum { NAN_ATTRIBUTE_CHANNEL_INFO = 228, NAN_ATTRIBUTE_NUM_CHANNELS = 229, NAN_ATTRIBUTE_INSTANT_MODE_ENABLE = 230, - NAN_ATTRIBUTE_INSTANT_COMM_CHAN = 231 + NAN_ATTRIBUTE_INSTANT_COMM_CHAN = 231, + NAN_ATTRIBUTE_CHRE_REQUEST = 232, } NAN_ATTRIBUTE; typedef enum { @@ -2543,6 +2544,7 @@ class NanMacControl : public WifiCommand wifi_interface_handle mIface; NanRequestType mType; u32 mVersion; + u8 mChreNan; public: NanMacControl(wifi_interface_handle iface, int id, @@ -2582,6 +2584,10 @@ class NanMacControl : public WifiCommand mParams = params; } + void setChreNan(u8 chre_nan) { + mChreNan = chre_nan; + } + int createRequest(WifiRequest& request) { ALOGI("NAN CMD: %s\n", NanCmdToString(mType)); if (mType == NAN_REQUEST_ENABLE) { @@ -2981,6 +2987,12 @@ class NanMacControl : public WifiCommand ALOGI("%s: instant mode channel = %d\n", __func__, mParams->instant_mode_channel); } + result = request.put_u8(NAN_ATTRIBUTE_CHRE_REQUEST, mChreNan); + if (result < 0) { + ALOGE("%s: Failing in config chreNan, result = %d\n", __func__, result); + return result; + } + request.attr_end(data); NAN_DBG_EXIT(); return WIFI_SUCCESS; @@ -2997,6 +3009,12 @@ class NanMacControl : public WifiCommand nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); + result = request.put_u8(NAN_ATTRIBUTE_CHRE_REQUEST, mChreNan); + if (result < 0) { + ALOGE("%s: Failing in config chreNan, result = %d\n", __func__, result); + return result; + } + request.attr_end(data); NAN_DBG_EXIT(); @@ -3254,13 +3272,15 @@ class NanMacControl : public WifiCommand } } - if (mParams->config_instant_mode_channel) { + if (mParams->enable_instant_mode && mParams->config_instant_mode_channel + && mParams->instant_mode_channel) { result = request.put_u32(NAN_ATTRIBUTE_INSTANT_COMM_CHAN, mParams->instant_mode_channel); if (result < 0) { ALOGE("%s: Failing in config instant channel, result = %d\n", __func__, result); return result; } + ALOGI("%s: instant mode channel = %d\n", __func__, mParams->instant_mode_channel); } request.attr_end(data); @@ -3320,6 +3340,10 @@ class NanMacControl : public WifiCommand return NL_SKIP; } + if (mChreNan) { + return NL_SKIP; + } + rsp_vndr_data = (nan_hal_resp_t *)reply.get_vendor_data(); ALOGI("NanMacControl::handleResponse\n"); if (mType == NAN_VERSION_INFO) { @@ -3399,6 +3423,10 @@ class NanMacControl : public WifiCommand return NL_SKIP; } + if (mChreNan) { + return NL_SKIP; + } + for (nl_iterator it(vendor_data); it.has_next(); it.next()) { attr_type = it.get_type(); @@ -3868,7 +3896,6 @@ static int get_svc_hash(unsigned char *svc_name, return WIFI_SUCCESS; } -#ifdef CONFIG_BRCM static int dump_NanEnableRequest(NanEnableRequest* msg) { ALOGI("%s: Dump NanEnableRequest msg:\n", __func__); @@ -3974,6 +4001,7 @@ static int dump_NanEnableRequest(NanEnableRequest* msg) return WIFI_SUCCESS; } +#ifdef CONFIG_BRCM static int dump_NanConfigRequestRequest(NanConfigRequest* msg) { ALOGI("%s: Dump NanConfigRequest msg:\n", __func__); @@ -4272,32 +4300,66 @@ void nan_reset_dbg_counters() } /////////////////////////////////////////////////////////////////////////////// -wifi_error nan_enable_request(transaction_id id, - wifi_interface_handle iface, NanEnableRequest* msg) +wifi_error nan_cmn_enabe_request(transaction_id id, + NanMacControl *cmd, NanEnableRequest* msg) { wifi_error ret = WIFI_SUCCESS; - wifi_handle handle = getWifiHandle(iface); - NanRequestType cmdType = NAN_REQUEST_ENABLE; - - ALOGI("Enabling Nan, Handle = %p\n", handle); - #ifdef CONFIG_BRCM // check up nan enable params from Nan manager level dump_NanEnableRequest(msg); #endif /* CONFIG_BRCM */ nan_reset_dbg_counters(); - /* XXX: WAR posting async enable response */ - //NanMacControl *cmd = new NanMacControl(iface, id, (void *)msg, cmdType); - NanMacControl *cmd = (NanMacControl*)(info.nan_mac_control); - NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); - cmd->setType(cmdType); + + cmd->setType(NAN_REQUEST_ENABLE); cmd->setId(id); cmd->setMsg((void *)msg); + ret = (wifi_error)cmd->start(); if (ret != WIFI_SUCCESS) { ALOGE("%s : failed in start, error = %d\n", __func__, ret); } - //cmd->releaseRef(); + + return ret; +} + +wifi_error nan_enable_request(transaction_id id, + wifi_interface_handle iface, NanEnableRequest* msg) +{ + wifi_error ret = WIFI_SUCCESS; + hal_info *h_info = getHalInfo(iface); + + ALOGE("nan_enable_request: nan_state = %d\n", h_info->nan_state); + +#ifdef CHRE_NAN + //check if host NAN is pre-empting CHRE NAN + if (h_info->nan_state == NAN_STATE_CHRE) { + /* notify pre-empt to chre */ + if (h_info->chre_nan_cb.on_chre_nan_rtt_change != NULL) { + h_info->chre_nan_cb.on_chre_nan_rtt_change(CHRE_PREMPTED); + } + /* first disable NAN for chre */ + ret = nan_chre_disable_request(1, iface); + if (ret != WIFI_SUCCESS) { + ALOGE("Failed to disable NAN for CHRE ret %d\n", ret); + return ret; + } + } + + /* notify unavailable status to chre */ + if (h_info->chre_nan_cb.on_chre_nan_rtt_change != NULL) { + h_info->chre_nan_cb.on_chre_nan_rtt_change(CHRE_UNAVAILABLE); + } +#endif /* CHRE_NAN */ + + NanMacControl *cmd = (NanMacControl*)(info.nan_mac_control); + NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); + cmd->setChreNan(0); + ret = nan_cmn_enabe_request(id, cmd, msg); + + if (ret == WIFI_SUCCESS) { + h_info->nan_state = NAN_STATE_AP; + } + return ret; } @@ -4312,16 +4374,40 @@ void nan_dump_dbg_counters() ALOGI("Num Transmit Success %d\n", counters.transmit_txs); } +wifi_error nan_cmn_disable_request(transaction_id id, NanMacControl *mac) +{ + wifi_error ret = WIFI_SUCCESS; + + nan_dump_dbg_counters(); + + mac->setType(NAN_REQUEST_DISABLE); + ret = (wifi_error)mac->cancel(); + if (ret != WIFI_SUCCESS) { + ALOGE("cancel failed, error = %d\n", ret); + } else { + ALOGE("Deinitializing Nan Mac Control = %p\n", mac); + } + mac->releaseRef(); + + return ret; +} wifi_error nan_disable_request(transaction_id id, wifi_interface_handle iface) { - wifi_handle handle = getWifiHandle(iface); - NanRequestType cmdType = NAN_REQUEST_DISABLE; wifi_error ret = WIFI_SUCCESS; + hal_info *h_info = getHalInfo(iface); + + ALOGE("nan_disable_request: nan_state %d\n", h_info->nan_state); + + if (h_info->nan_state == NAN_STATE_CHRE) { + ALOGE("nan_disable_request: Not enabled for AP.. return\n"); + return ret; + } - ALOGI("Disabling Nan, Handle = %p\n", handle); - NanMacControl *cmd = new NanMacControl(iface, id, NULL, cmdType); NanMacControl *mac_prim = (NanMacControl*)(info.nan_mac_control); + NanMacControl *cmd = new NanMacControl(iface, id, NULL, NAN_REQUEST_LAST); + + NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); if (id != NAN_MAC_INVALID_TRANSID) { ALOGE("Disable NAN MAC transId= %d\n", id); @@ -4330,17 +4416,15 @@ wifi_error nan_disable_request(transaction_id id, ALOGE("Invalid transId= %d cur= %d\n", id, mac_prim->getId()); } - NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); - - nan_dump_dbg_counters(); - - ret = (wifi_error)cmd->cancel(); - if (ret != WIFI_SUCCESS) { - ALOGE("cancel failed, error = %d\n", ret); - } else { - ALOGE("Deinitializing Nan Mac Control = %p\n", cmd); + cmd->setChreNan(0); + ret = nan_cmn_disable_request(id, cmd); + if (ret == WIFI_SUCCESS) { + h_info->nan_state = NAN_STATE_DISABLED; + /* notify pre-empt / unavailable status to chre */ + if (h_info->chre_nan_cb.on_chre_nan_rtt_change != NULL) { + h_info->chre_nan_cb.on_chre_nan_rtt_change(CHRE_AVAILABLE); + } } - cmd->releaseRef(); return ret; } @@ -5437,3 +5521,89 @@ wifi_error nan_data_end(transaction_id id, NAN_DBG_EXIT(); return ret; } + +wifi_error nan_chre_enable_request(transaction_id id, + wifi_interface_handle iface, NanEnableRequest* msg) +{ + wifi_error ret = WIFI_SUCCESS; + NanEnableRequest def_msg; + hal_info *h_info = getHalInfo(iface); + + ALOGI("nan_chre_enable_request: nan_state %d\n", h_info->nan_state); + + if (h_info->nan_state == NAN_STATE_CHRE) { + return WIFI_SUCCESS; + } else if (h_info->nan_state == NAN_STATE_AP) { + ALOGE("nan_chre_enable_request: Nan is enabled for AP. Fail CHRE request\n"); + return WIFI_ERROR_BUSY; + } + + NanMacControl *mac = new NanMacControl(iface, 0, NULL, NAN_REQUEST_LAST); + NULL_CHECK_RETURN(mac, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); + + mac->setChreNan(1); + if (msg == NULL) { + /* default enable params */ + ALOGI("Input Enable config is NULL, use default config\n"); + memset(&def_msg, 0, sizeof(def_msg)); + def_msg.hop_count_limit_val = 5; + def_msg.config_2dot4g_support = 1; + def_msg.support_2dot4g_val = 1; + def_msg.config_2dot4g_beacons = 1; + def_msg.beacon_2dot4g_val = 1; + def_msg.config_2dot4g_sdf = 1; + def_msg.sdf_2dot4g_val = 1; + def_msg.config_disc_mac_addr_randomization = true; + def_msg.disc_mac_addr_rand_interval_sec = 0; + def_msg.config_ndpe_attr = false; + ret = nan_cmn_enabe_request(id, mac, &def_msg); + } else { + ret = nan_cmn_enabe_request(id, mac, msg); + } + + if (ret == WIFI_SUCCESS) { + h_info->nan_state = NAN_STATE_CHRE; + } + + return ret; +} + +wifi_error nan_chre_disable_request(transaction_id id, + wifi_interface_handle iface) +{ + wifi_error ret = WIFI_SUCCESS; + hal_info *h_info = getHalInfo(iface); + + ALOGI("nan_chre_disable_request: nan_state %d\n", h_info->nan_state); + + if (h_info->nan_state == NAN_STATE_AP) { + ALOGE("nan_chre_disable_request: Not enabled for CHRE.. return\n"); + return ret; + } + + NanMacControl *cmd = new NanMacControl(iface, id, NULL, NAN_REQUEST_LAST); + NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); + + cmd->setChreNan(1); + ret = nan_cmn_disable_request(id, cmd); + + if (ret == WIFI_SUCCESS) { + h_info->nan_state = NAN_STATE_DISABLED; + } + + return ret; +} + +wifi_error nan_chre_register_handler(wifi_interface_handle iface, + wifi_chre_handler handler) +{ + wifi_error ret = WIFI_SUCCESS; + hal_info *h_info = getHalInfo(iface); + + if (h_info) { + ALOGE("Registering CHRE handler for Nan Status %p\n", handler.on_chre_nan_rtt_change); + h_info->chre_nan_cb = handler; + } + + return ret; +} diff --git a/bcmdhd/wifi_hal/wifi_hal.cpp b/bcmdhd/wifi_hal/wifi_hal.cpp index 83c65c3..fe679ab 100755 --- a/bcmdhd/wifi_hal/wifi_hal.cpp +++ b/bcmdhd/wifi_hal/wifi_hal.cpp @@ -94,6 +94,8 @@ static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle hand static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface, u8 enable); static wifi_error wifi_get_usable_channels(wifi_handle handle, u32 band_mask, u32 iface_mode_mask, u32 filter_mask, u32 max_size, u32* size, wifi_usable_channel* channels); +static wifi_error wifi_get_supported_radio_combinations_matrix(wifi_handle handle, + u32 max_size, u32* size, wifi_radio_combination_matrix *radio_combination_matrix); static void wifi_cleanup_dynamic_ifaces(wifi_handle handle); typedef enum wifi_attr { @@ -116,6 +118,13 @@ typedef enum wifi_attr { ANDR_WIFI_ATTRIBUTE_MAX } wifi_attr_t; +enum wifi_radio_combo_attributes { + ANDR_WIFI_ATTRIBUTE_RADIO_COMBO_INVALID = 0, + ANDR_WIFI_ATTRIBUTE_RADIO_COMBO_MATRIX = 1, + // Add more attribute here + ANDR_WIFI_ATTRIBUTE_RADIO_COMBO_MAX +}; + enum wifi_rssi_monitor_attr { RSSI_MONITOR_ATTRIBUTE_INVALID = 0, RSSI_MONITOR_ATTRIBUTE_MAX_RSSI = 1, @@ -331,6 +340,10 @@ wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) fn->wifi_set_dtim_config = wifi_set_dtim_config; fn->wifi_get_usable_channels = wifi_get_usable_channels; fn->wifi_trigger_subsystem_restart = wifi_trigger_subsystem_restart; + fn->wifi_get_supported_radio_combinations_matrix = wifi_get_supported_radio_combinations_matrix; + fn->wifi_nan_rtt_chre_enable_request = nan_chre_enable_request; + fn->wifi_nan_rtt_chre_disable_request = nan_chre_disable_request; + fn->wifi_chre_register_handler = nan_chre_register_handler; return WIFI_SUCCESS; } @@ -530,6 +543,7 @@ wifi_error wifi_initialize(wifi_handle *handle) } } else { ALOGI("Not Calling set alert handler as global_iface is NULL"); + return WIFI_ERROR_UNKNOWN; } return WIFI_SUCCESS; } @@ -1478,6 +1492,93 @@ protected: } }; +///////////////////////////////////////////////////////////////////// +class GetRadioComboCommand : public WifiCommand { +private: + wifi_radio_combination_matrix *rcmatrix; + u32* rc_size; + u32 set_size_max; + int ret = 0; + +public: + GetRadioComboCommand(wifi_interface_handle handle, u32 max_size, u32* size, + wifi_radio_combination_matrix *radio_combination_matrix) + : WifiCommand("GetRadioComboCommand", handle, 0), rcmatrix(radio_combination_matrix), + rc_size(size), set_size_max(max_size) + { + } + + virtual int createRequest(WifiRequest& mMsg) { + ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_RADIO_COMBO_MATRIX); + if (ret < 0) { + ALOGE("Can't create message to send to driver - %d", ret); + } + nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA); + mMsg.attr_end(data); + + return ret; + } + + int start() { + WifiRequest request(familyId(), ifaceId()); + ret = createRequest(request); + if (ret < 0) { + ALOGE("Request failed for radio_combo_matrix, result = %d", ret); + return ret; + } + ret = requestResponse(request); + if (ret < 0) { + ALOGE("Request Response failed for radio_combo_matrix, result = %d", ret); + return ret; + } + ALOGD("Done! %s", __FUNCTION__); + return ret; + } + +protected: + virtual int handleResponse(WifiEvent& reply) { + ALOGD("In GetRadioComboCommand::handleResponse"); + if (reply.get_cmd() != NL80211_CMD_VENDOR) { + ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); + return NL_SKIP; + } + + int id = reply.get_vendor_id(); + int subcmd = reply.get_vendor_subcmd(); + + nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA); + int len = reply.get_vendor_data_len(); + + ALOGV("Id = %0x, subcmd = %d, len = %d", id, subcmd, len); + if (vendor_data == NULL || len == 0) { + ALOGE("no vendor data in GetRadioComboCommand response; ignoring it"); + return NL_SKIP; + } + + for (nl_iterator it(vendor_data); it.has_next(); it.next()) { + if (it.get_type() == ANDR_WIFI_ATTRIBUTE_RADIO_COMBO_MATRIX) { + void *data = it.get_data(); + *rc_size = it.get_len(); + if (!data || !*rc_size) { + ALOGE("Buffers pointers not set"); + return NL_SKIP; + } + if (set_size_max < *rc_size) { + ALOGE("Unexpected buffers size"); + return NL_SKIP; + } + memcpy(rcmatrix, data, min(len, *rc_size)); + } else { + ALOGW("Ignoring invalid attribute type = %d, size = %d", + it.get_type(), it.get_len()); + } + } + + ALOGD("GetRadioComboCommand::Success"); + return NL_OK; + } +}; +///////////////////////////////////////////////////////////////////// class SetLatencyModeCommand : public WifiCommand { private: @@ -1759,6 +1860,27 @@ wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int set_siz return (wifi_error) command.requestResponse(); } +wifi_error wifi_get_supported_radio_combinations_matrix(wifi_handle handle, + u32 max_size, u32* size, wifi_radio_combination_matrix *radio_combination_matrix) +{ + int numIfaceHandles = 0; + wifi_interface_handle *ifaceHandles = NULL; + wifi_interface_handle wlan0Handle; + + wlan0Handle = wifi_get_wlan_interface((wifi_handle)handle, ifaceHandles, numIfaceHandles); + GetRadioComboCommand *cmd = new GetRadioComboCommand(wlan0Handle, max_size, + size, radio_combination_matrix); + NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); + wifi_error result = (wifi_error)cmd->start(); + if (result == WIFI_SUCCESS) { + ALOGD("Get radio combo matrix success"); + } else { + ALOGE("Get radio combo matrix failed\n"); + } + cmd->releaseRef(); + return result; +} + wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui) { SetPnoMacAddrOuiCommand command(handle, scan_oui); diff --git a/bcmdhd/wifi_hal/wifi_logger.cpp b/bcmdhd/wifi_hal/wifi_logger.cpp index 2a06cfb..1ee9661 100755 --- a/bcmdhd/wifi_hal/wifi_logger.cpp +++ b/bcmdhd/wifi_hal/wifi_logger.cpp @@ -72,7 +72,9 @@ typedef enum { LOGGER_FILE_DUMP_DONE_IND, LOGGER_SET_HAL_START, LOGGER_HAL_STOP, - LOGGER_SET_HAL_PID + LOGGER_SET_HAL_PID, + LOGGER_SET_TPUT_DEBUG_DUMP_CMD, + LOGGER_GET_BUF_RING_MAP } DEBUG_SUB_COMMAND; #define MAX_NV_FILE 4 @@ -118,6 +120,8 @@ typedef enum { LOGGER_ATTRIBUTE_PKT_FATE_NUM = 17, LOGGER_ATTRIBUTE_PKT_FATE_DATA = 18, LOGGER_ATTRIBUTE_HANG_REASON = 19, + LOGGER_ATTRIBUTE_BUF_RING_NUM = 20, + LOGGER_ATTRIBUTE_BUF_RING_MAP = 21, /* Add new attributes just above this */ LOGGER_ATTRIBUTE_MAX } LOGGER_ATTRIBUTE; @@ -137,6 +141,7 @@ typedef enum { GET_RING_STATUS, GET_FEATURE, START_RING_LOG, + GET_BUF_RING_MAP, } GetCmdType; typedef enum { @@ -189,6 +194,323 @@ typedef enum { #define HAL_START_REQUEST_ID 2 #define HAL_RESTART_ID 3 #define FILE_NAME_LEN 256 +#define RING_NAME_LEN 32 +#if defined(RING_DUMP) +/* Loglevel */ +#define DUMP_DEBUG(x) +#define DUMP_INFO(x) ALOGI x +#define FILE_DUMP_REQUEST_ID 2 +#define C2S(x) case x: return #x; +static const char *EWP_EventAttrToString(int len_attr); +static const char *EWP_CmdAttrToString(int data_attr); + +typedef struct buf_data { + u32 ver; /* version of struct */ + u32 len; /* Total len */ + /* size of each buffer in case of split buffers (0 - single buffer). */ + u32 buf_threshold; + const void *data_buf[1]; /* array of user space buffer pointers.*/ +} buf_data_t; + +/* Attributes associated with GOOGLE_FILE_DUMP_EVENT */ +typedef enum { + DUMP_LEN_ATTR_INVALID = 0, + DUMP_LEN_ATTR_MEMDUMP = 1, + DUMP_LEN_ATTR_SSSR_C0_BEFORE = 2, + DUMP_LEN_ATTR_SSSR_C0_AFTER = 3, + DUMP_LEN_ATTR_SSSR_C1_BEFORE = 4, + DUMP_LEN_ATTR_SSSR_C1_AFTER = 5, + DUMP_LEN_ATTR_SSSR_C2_BEFORE = 6, + DUMP_LEN_ATTR_SSSR_C2_AFTER = 7, + DUMP_LEN_ATTR_SSSR_DIG_BEFORE = 8, + DUMP_LEN_ATTR_SSSR_DIG_AFTER = 9, + DUMP_LEN_ATTR_TIMESTAMP = 10, + DUMP_LEN_ATTR_GENERAL_LOG = 11, + DUMP_LEN_ATTR_ECNTRS = 12, + DUMP_LEN_ATTR_SPECIAL_LOG = 13, + DUMP_LEN_ATTR_DHD_DUMP = 14, + DUMP_LEN_ATTR_EXT_TRAP = 15, + DUMP_LEN_ATTR_HEALTH_CHK = 16, + DUMP_LEN_ATTR_PRESERVE_LOG = 17, + DUMP_LEN_ATTR_COOKIE = 18, + DUMP_LEN_ATTR_FLOWRING_DUMP = 19, + DUMP_LEN_ATTR_PKTLOG = 20, + DUMP_LEN_ATTR_PKTLOG_DEBUG = 21, + DUMP_FILENAME_ATTR_DEBUG_DUMP = 22, + DUMP_FILENAME_ATTR_MEM_DUMP = 23, + DUMP_FILENAME_ATTR_SSSR_CORE_0_BEFORE_DUMP = 24, + DUMP_FILENAME_ATTR_SSSR_CORE_0_AFTER_DUMP = 25, + DUMP_FILENAME_ATTR_SSSR_CORE_1_BEFORE_DUMP = 26, + DUMP_FILENAME_ATTR_SSSR_CORE_1_AFTER_DUMP = 27, + DUMP_FILENAME_ATTR_SSSR_CORE_2_BEFORE_DUMP = 28, + DUMP_FILENAME_ATTR_SSSR_CORE_2_AFTER_DUMP = 29, + DUMP_FILENAME_ATTR_SSSR_DIG_BEFORE_DUMP = 30, + DUMP_FILENAME_ATTR_SSSR_DIG_AFTER_DUMP = 31, + DUMP_FILENAME_ATTR_PKTLOG_DUMP = 32, + DUMP_FILENAME_ATTR_PKTLOG_DEBUG_DUMP = 33, + DUMP_LEN_ATTR_STATUS_LOG = 34, + DUMP_LEN_ATTR_AXI_ERROR = 35, + DUMP_FILENAME_ATTR_AXI_ERROR_DUMP = 36, + DUMP_LEN_ATTR_RTT_LOG = 37, + DUMP_LEN_ATTR_SDTC_ETB_DUMP = 38, + DUMP_FILENAME_ATTR_SDTC_ETB_DUMP = 39, + DUMP_LEN_ATTR_PKTID_MAP_LOG = 40, + DUMP_LEN_ATTR_PKTID_UNMAP_LOG = 41, + DUMP_LEN_ATTR_EWP_HW_INIT_LOG = 42, + DUMP_LEN_ATTR_EWP_HW_MOD_DUMP = 43, + DUMP_LEN_ATTR_EWP_HW_REG_DUMP = 44, + /* Please add new attributes from here to sync up old DHD */ + DUMP_EVENT_ATTR_MAX = 45, +} EWP_DUMP_EVENT_ATTRIBUTE; + +/* Attributes associated with DEBUG_GET_DUMP_BUF */ +typedef enum { + DUMP_BUF_ATTR_INVALID = 0, + DUMP_BUF_ATTR_MEMDUMP = 1, + DUMP_BUF_ATTR_SSSR_C0_BEFORE = 2, + DUMP_BUF_ATTR_SSSR_C0_AFTER = 3, + DUMP_BUF_ATTR_SSSR_C1_BEFORE = 4, + DUMP_BUF_ATTR_SSSR_C1_AFTER = 5, + DUMP_BUF_ATTR_SSSR_C2_BEFORE = 6, + DUMP_BUF_ATTR_SSSR_C2_AFTER = 7, + DUMP_BUF_ATTR_SSSR_DIG_BEFORE = 8, + DUMP_BUF_ATTR_SSSR_DIG_AFTER = 9, + DUMP_BUF_ATTR_TIMESTAMP = 10, + DUMP_BUF_ATTR_GENERAL_LOG = 11, + DUMP_BUF_ATTR_ECNTRS = 12, + DUMP_BUF_ATTR_SPECIAL_LOG = 13, + DUMP_BUF_ATTR_DHD_DUMP = 14, + DUMP_BUF_ATTR_EXT_TRAP = 15, + DUMP_BUF_ATTR_HEALTH_CHK = 16, + DUMP_BUF_ATTR_PRESERVE_LOG = 17, + DUMP_BUF_ATTR_COOKIE = 18, + DUMP_BUF_ATTR_FLOWRING_DUMP = 19, + DUMP_BUF_ATTR_PKTLOG = 20, + DUMP_BUF_ATTR_PKTLOG_DEBUG = 21, + DUMP_BUF_ATTR_STATUS_LOG = 22, + DUMP_BUF_ATTR_AXI_ERROR = 23, + DUMP_BUF_ATTR_RTT_LOG = 24, + DUMP_BUF_ATTR_SDTC_ETB_DUMP = 25, + DUMP_BUF_ATTR_PKTID_MAP_LOG = 26, + DUMP_BUF_ATTR_PKTID_UNMAP_LOG = 27, + DUMP_BUF_ATTR_EWP_HW_INIT_LOG = 28, + DUMP_BUF_ATTR_EWP_HW_MOD_DUMP = 29, + DUMP_BUF_ATTR_EWP_HW_REG_DUMP = 30, + /* Please add new attributes from here to sync up old DHD */ + DUMP_BUF_ATTR_MAX = 31, +} EWP_DUMP_CMD_ATTRIBUTE; + +typedef enum { + DUMP_TYPE_MEM_DUMP = 0, + DUMP_TYPE_DEBUG_DUMP = 1, + DUMP_TYPE_SSSR_CORE0_BEF_DUMP = 2, + DUMP_TYPE_SSSR_CORE0_AFT_DUMP = 3, + DUMP_TYPE_SSSR_CORE1_BEF_DUMP = 4, + DUMP_TYPE_SSSR_CORE1_AFT_DUMP = 5, + DUMP_TYPE_SSSR_CORE2_BEF_DUMP = 6, + DUMP_TYPE_SSSR_CORE2_AFT_DUMP = 7, + DUMP_TYPE_SSSR_DIG_BEF_DUMP = 8, + DUMP_TYPE_SSSR_DIG_AFT_DUMP = 9, + DUMP_TYPE_PKTLOG_DUMP = 10, + DUMP_TYPE_PKTLOG_DEBUG_DUMP = 11, + DUMP_TYPE_AXI_ERROR_DUMP = 12, + DUMP_TYPE_D2H_MINI_DUMP = 13, + DUMP_TYPE_SDTC_ETB_DUMP = 14, + /* Please add new attributes from here to sync up old DHD */ + DUMP_TYPE_MAX = 15, +} EWP_DUMP_TYPE; + +/* Struct for table which has len_attr, data_attr and dump file type attr */ +typedef struct logger_attr_entry { + u8 attr_type; /* Type of attribute */ + u8 buf_attr; /* Buffer associated with the attribute */ + u8 dump_type; /* Each attribute will be linked to a dump type */ +} logger_attr_entry_t; + +logger_attr_entry_t attr_lookup_tbl[] = { + /* Mem Dump Block */ + {DUMP_FILENAME_ATTR_MEM_DUMP, 0, DUMP_TYPE_MEM_DUMP}, + {DUMP_LEN_ATTR_MEMDUMP, DUMP_BUF_ATTR_MEMDUMP, DUMP_TYPE_MEM_DUMP}, + /* SSSR Dump Block */ + {DUMP_FILENAME_ATTR_SSSR_CORE_0_BEFORE_DUMP, 0, DUMP_TYPE_SSSR_CORE0_BEF_DUMP}, + {DUMP_LEN_ATTR_SSSR_C0_BEFORE, DUMP_BUF_ATTR_SSSR_C0_BEFORE, DUMP_TYPE_SSSR_CORE0_BEF_DUMP}, + + {DUMP_FILENAME_ATTR_SSSR_CORE_0_AFTER_DUMP, 0, DUMP_TYPE_SSSR_CORE0_AFT_DUMP}, + {DUMP_LEN_ATTR_SSSR_C0_AFTER, DUMP_BUF_ATTR_SSSR_C0_AFTER, DUMP_TYPE_SSSR_CORE0_AFT_DUMP}, + + {DUMP_FILENAME_ATTR_SSSR_CORE_1_BEFORE_DUMP, 0, DUMP_TYPE_SSSR_CORE1_BEF_DUMP}, + {DUMP_LEN_ATTR_SSSR_C1_BEFORE, DUMP_BUF_ATTR_SSSR_C1_BEFORE, DUMP_TYPE_SSSR_CORE1_BEF_DUMP}, + + {DUMP_FILENAME_ATTR_SSSR_CORE_1_AFTER_DUMP, 0, DUMP_TYPE_SSSR_CORE1_AFT_DUMP}, + {DUMP_LEN_ATTR_SSSR_C1_AFTER, DUMP_BUF_ATTR_SSSR_C1_AFTER, DUMP_TYPE_SSSR_CORE1_AFT_DUMP}, + + {DUMP_FILENAME_ATTR_SSSR_CORE_2_BEFORE_DUMP, 0, DUMP_TYPE_SSSR_CORE2_BEF_DUMP}, + {DUMP_LEN_ATTR_SSSR_C2_BEFORE, DUMP_BUF_ATTR_SSSR_C2_BEFORE, DUMP_TYPE_SSSR_CORE2_BEF_DUMP}, + + {DUMP_FILENAME_ATTR_SSSR_CORE_2_AFTER_DUMP, 0, DUMP_TYPE_SSSR_CORE2_AFT_DUMP}, + {DUMP_LEN_ATTR_SSSR_C2_AFTER, DUMP_BUF_ATTR_SSSR_C2_AFTER, DUMP_TYPE_SSSR_CORE2_AFT_DUMP}, + + {DUMP_FILENAME_ATTR_SSSR_DIG_BEFORE_DUMP, 0, DUMP_TYPE_SSSR_DIG_BEF_DUMP}, + {DUMP_LEN_ATTR_SSSR_DIG_BEFORE, DUMP_BUF_ATTR_SSSR_DIG_BEFORE, DUMP_TYPE_SSSR_DIG_BEF_DUMP}, + + {DUMP_FILENAME_ATTR_SSSR_DIG_AFTER_DUMP, 0, DUMP_TYPE_SSSR_DIG_AFT_DUMP}, + {DUMP_LEN_ATTR_SSSR_DIG_AFTER, DUMP_BUF_ATTR_SSSR_DIG_AFTER, DUMP_TYPE_SSSR_DIG_AFT_DUMP}, + + /* Debug Dump Block */ + {DUMP_FILENAME_ATTR_DEBUG_DUMP, 0, DUMP_TYPE_DEBUG_DUMP}, + {DUMP_LEN_ATTR_TIMESTAMP, DUMP_BUF_ATTR_TIMESTAMP, DUMP_TYPE_DEBUG_DUMP}, + {DUMP_LEN_ATTR_GENERAL_LOG, DUMP_BUF_ATTR_GENERAL_LOG, DUMP_TYPE_DEBUG_DUMP}, + {DUMP_LEN_ATTR_ECNTRS, DUMP_BUF_ATTR_ECNTRS, DUMP_TYPE_DEBUG_DUMP}, + {DUMP_LEN_ATTR_SPECIAL_LOG, DUMP_BUF_ATTR_SPECIAL_LOG, DUMP_TYPE_DEBUG_DUMP}, + {DUMP_LEN_ATTR_DHD_DUMP, DUMP_BUF_ATTR_DHD_DUMP, DUMP_TYPE_DEBUG_DUMP}, + {DUMP_LEN_ATTR_EXT_TRAP, DUMP_BUF_ATTR_EXT_TRAP, DUMP_TYPE_DEBUG_DUMP}, + {DUMP_LEN_ATTR_HEALTH_CHK, DUMP_BUF_ATTR_HEALTH_CHK, DUMP_TYPE_DEBUG_DUMP}, + {DUMP_LEN_ATTR_PRESERVE_LOG, DUMP_BUF_ATTR_PRESERVE_LOG, DUMP_TYPE_DEBUG_DUMP}, + {DUMP_LEN_ATTR_COOKIE, DUMP_BUF_ATTR_COOKIE, DUMP_TYPE_DEBUG_DUMP}, + {DUMP_LEN_ATTR_FLOWRING_DUMP, DUMP_BUF_ATTR_FLOWRING_DUMP, DUMP_TYPE_DEBUG_DUMP}, + {DUMP_LEN_ATTR_STATUS_LOG, DUMP_BUF_ATTR_STATUS_LOG, DUMP_TYPE_DEBUG_DUMP}, + {DUMP_LEN_ATTR_RTT_LOG, DUMP_BUF_ATTR_RTT_LOG, DUMP_TYPE_DEBUG_DUMP}, + {DUMP_LEN_ATTR_PKTID_MAP_LOG, DUMP_BUF_ATTR_PKTID_MAP_LOG, DUMP_TYPE_DEBUG_DUMP}, + {DUMP_LEN_ATTR_PKTID_UNMAP_LOG, DUMP_BUF_ATTR_PKTID_UNMAP_LOG, DUMP_TYPE_DEBUG_DUMP}, + {DUMP_LEN_ATTR_EWP_HW_INIT_LOG, DUMP_BUF_ATTR_EWP_HW_INIT_LOG, DUMP_TYPE_DEBUG_DUMP}, + {DUMP_LEN_ATTR_EWP_HW_MOD_DUMP, DUMP_BUF_ATTR_EWP_HW_MOD_DUMP, DUMP_TYPE_DEBUG_DUMP}, + {DUMP_LEN_ATTR_EWP_HW_REG_DUMP, DUMP_BUF_ATTR_EWP_HW_REG_DUMP, DUMP_TYPE_DEBUG_DUMP}, + + /* PKT log dump block */ + {DUMP_FILENAME_ATTR_PKTLOG_DUMP, 0, DUMP_TYPE_PKTLOG_DUMP}, + {DUMP_LEN_ATTR_PKTLOG, DUMP_BUF_ATTR_PKTLOG, DUMP_TYPE_PKTLOG_DUMP}, + {DUMP_FILENAME_ATTR_PKTLOG_DEBUG_DUMP, 0, DUMP_TYPE_PKTLOG_DEBUG_DUMP}, + {DUMP_LEN_ATTR_PKTLOG_DEBUG, DUMP_BUF_ATTR_PKTLOG_DEBUG, DUMP_TYPE_PKTLOG_DEBUG_DUMP}, + /* AXI error log dump block */ + {DUMP_FILENAME_ATTR_AXI_ERROR_DUMP, 0, DUMP_TYPE_AXI_ERROR_DUMP}, + {DUMP_LEN_ATTR_AXI_ERROR, DUMP_BUF_ATTR_AXI_ERROR, DUMP_TYPE_AXI_ERROR_DUMP}, + /* SDTC etb log dump block */ + {DUMP_FILENAME_ATTR_SDTC_ETB_DUMP, 0, DUMP_TYPE_SDTC_ETB_DUMP}, + {DUMP_LEN_ATTR_SDTC_ETB_DUMP, DUMP_BUF_ATTR_SDTC_ETB_DUMP, DUMP_TYPE_SDTC_ETB_DUMP}, + {DUMP_EVENT_ATTR_MAX, 0, 0}, +}; + +static const char *EWP_EventAttrToString(int len_attr) +{ + switch (len_attr) { + C2S(DUMP_LEN_ATTR_MEMDUMP) + C2S(DUMP_LEN_ATTR_SSSR_C0_BEFORE) + C2S(DUMP_LEN_ATTR_SSSR_C0_AFTER) + C2S(DUMP_LEN_ATTR_SSSR_C1_BEFORE) + C2S(DUMP_LEN_ATTR_SSSR_C1_AFTER) + C2S(DUMP_LEN_ATTR_SSSR_C2_BEFORE) + C2S(DUMP_LEN_ATTR_SSSR_C2_AFTER) + C2S(DUMP_LEN_ATTR_SSSR_DIG_BEFORE) + C2S(DUMP_LEN_ATTR_SSSR_DIG_AFTER) + C2S(DUMP_LEN_ATTR_TIMESTAMP) + C2S(DUMP_LEN_ATTR_GENERAL_LOG) + C2S(DUMP_LEN_ATTR_ECNTRS) + C2S(DUMP_LEN_ATTR_SPECIAL_LOG) + C2S(DUMP_LEN_ATTR_DHD_DUMP) + C2S(DUMP_LEN_ATTR_EXT_TRAP) + C2S(DUMP_LEN_ATTR_HEALTH_CHK) + C2S(DUMP_LEN_ATTR_PRESERVE_LOG) + C2S(DUMP_LEN_ATTR_COOKIE) + C2S(DUMP_LEN_ATTR_FLOWRING_DUMP) + C2S(DUMP_LEN_ATTR_PKTLOG) + C2S(DUMP_LEN_ATTR_PKTLOG_DEBUG) + C2S(DUMP_LEN_ATTR_STATUS_LOG) + C2S(DUMP_FILENAME_ATTR_DEBUG_DUMP) + C2S(DUMP_FILENAME_ATTR_MEM_DUMP) + C2S(DUMP_FILENAME_ATTR_SSSR_CORE_0_BEFORE_DUMP) + C2S(DUMP_FILENAME_ATTR_SSSR_CORE_0_AFTER_DUMP) + C2S(DUMP_FILENAME_ATTR_SSSR_CORE_1_BEFORE_DUMP) + C2S(DUMP_FILENAME_ATTR_SSSR_CORE_1_AFTER_DUMP) + C2S(DUMP_FILENAME_ATTR_SSSR_CORE_2_BEFORE_DUMP) + C2S(DUMP_FILENAME_ATTR_SSSR_CORE_2_AFTER_DUMP) + C2S(DUMP_FILENAME_ATTR_SSSR_DIG_BEFORE_DUMP) + C2S(DUMP_FILENAME_ATTR_SSSR_DIG_AFTER_DUMP) + C2S(DUMP_FILENAME_ATTR_PKTLOG_DUMP) + C2S(DUMP_FILENAME_ATTR_PKTLOG_DEBUG_DUMP) + C2S(DUMP_LEN_ATTR_AXI_ERROR) + C2S(DUMP_FILENAME_ATTR_AXI_ERROR_DUMP) + C2S(DUMP_LEN_ATTR_RTT_LOG) + C2S(DUMP_FILENAME_ATTR_SDTC_ETB_DUMP) + C2S(DUMP_LEN_ATTR_SDTC_ETB_DUMP) + C2S(DUMP_LEN_ATTR_PKTID_MAP_LOG) + C2S(DUMP_LEN_ATTR_PKTID_UNMAP_LOG) + C2S(DUMP_LEN_ATTR_EWP_HW_INIT_LOG) + C2S(DUMP_LEN_ATTR_EWP_HW_MOD_DUMP) + C2S(DUMP_LEN_ATTR_EWP_HW_REG_DUMP) + default: + return "DUMP_LEN_ATTR_INVALID"; + } +} + +static const char *EWP_CmdAttrToString(int attr) +{ + switch (attr) { + C2S(DUMP_BUF_ATTR_MEMDUMP) + C2S(DUMP_BUF_ATTR_SSSR_C0_BEFORE) + C2S(DUMP_BUF_ATTR_SSSR_C0_AFTER) + C2S(DUMP_BUF_ATTR_SSSR_C1_BEFORE) + C2S(DUMP_BUF_ATTR_SSSR_C1_AFTER) + C2S(DUMP_BUF_ATTR_SSSR_C2_BEFORE) + C2S(DUMP_BUF_ATTR_SSSR_C2_AFTER) + C2S(DUMP_BUF_ATTR_SSSR_DIG_BEFORE) + C2S(DUMP_BUF_ATTR_SSSR_DIG_AFTER) + C2S(DUMP_BUF_ATTR_TIMESTAMP) + C2S(DUMP_BUF_ATTR_GENERAL_LOG) + C2S(DUMP_BUF_ATTR_ECNTRS) + C2S(DUMP_BUF_ATTR_SPECIAL_LOG) + C2S(DUMP_BUF_ATTR_DHD_DUMP) + C2S(DUMP_BUF_ATTR_EXT_TRAP) + C2S(DUMP_BUF_ATTR_HEALTH_CHK) + C2S(DUMP_BUF_ATTR_PRESERVE_LOG) + C2S(DUMP_BUF_ATTR_COOKIE) + C2S(DUMP_BUF_ATTR_FLOWRING_DUMP) + C2S(DUMP_BUF_ATTR_PKTLOG) + C2S(DUMP_BUF_ATTR_PKTLOG_DEBUG) + C2S(DUMP_BUF_ATTR_STATUS_LOG) + C2S(DUMP_BUF_ATTR_AXI_ERROR) + C2S(DUMP_BUF_ATTR_RTT_LOG) + C2S(DUMP_BUF_ATTR_SDTC_ETB_DUMP) + C2S(DUMP_BUF_ATTR_PKTID_MAP_LOG) + C2S(DUMP_BUF_ATTR_PKTID_UNMAP_LOG) + C2S(DUMP_BUF_ATTR_EWP_HW_INIT_LOG) + C2S(DUMP_BUF_ATTR_EWP_HW_MOD_DUMP) + C2S(DUMP_BUF_ATTR_EWP_HW_REG_DUMP) + default: + return "DUMP_BUF_ATTR_INVALID"; + } +} + +/* Return index for matching buffer attribute */ +static int logger_attr_buffer_lookup(u8 attr) { + for (u8 i = 0; i < ARRAYSIZE(attr_lookup_tbl); i++) { + if (attr == attr_lookup_tbl[i].buf_attr) { + return i; + } + } + ALOGE("Lookup for buf attr = %s failed\n", + EWP_CmdAttrToString(attr)); + return -1; +} + +/* Return index matching the length attribute */ +static int logger_attr_lookup(u8 attr) { + for (u8 i = 0; i < ARRAYSIZE(attr_lookup_tbl); i++) { + if (attr == attr_lookup_tbl[i].attr_type) { + return i; + } + } + ALOGE("Lookup for len attr = %s failed\n", + EWP_EventAttrToString(attr)); + return -1; +} +#endif /* RING_DUMP */ + +#define DBGRING_NAME_MAX 32 //Copy from legacy hal +typedef struct wifi_buf_ring_map_entry { + uint32_t type; + uint32_t ring_id; + char ring_name[DBGRING_NAME_MAX]; +} wifi_buf_ring_map_entry_t; typedef struct { char hw_id[PROPERTY_VALUE_MAX]; @@ -217,6 +539,8 @@ class DebugCommand : public WifiCommand int *mBuffSize; u32 *mNumRings; wifi_ring_buffer_status *mStatus; + u32 *mNumMaps; + wifi_buf_ring_map_entry_t *mMaps; unsigned int *mSupport; u32 mVerboseLevel; u32 mFlags; @@ -290,6 +614,14 @@ public: mRingName = NULL; } + // constructor for buf ring map + DebugCommand(wifi_interface_handle iface, u32 *num_maps, + wifi_buf_ring_map_entry_t *map, GetCmdType cmdType) + : WifiCommand("DebugCommand", iface, 0), mNumMaps(num_maps), mMaps(map), mType(cmdType) + { + memset(mMaps, 0, sizeof(wifi_buf_ring_map_entry_t) * (*mNumMaps)); + } + // constructor for ring params DebugCommand(wifi_interface_handle iface, u32 verbose_level, u32 flags, u32 max_interval_sec, u32 min_data_size, char *ring_name, GetCmdType cmdType) @@ -428,6 +760,16 @@ public: break; } + case GET_BUF_RING_MAP: + { + result = request.create(GOOGLE_OUI, LOGGER_GET_BUF_RING_MAP); + if (result != WIFI_SUCCESS) { + ALOGE("Failed to create get ring status request; result = %d", result); + return result; + } + break; + } + case START_RING_LOG: result = createRingRequest(request); break; @@ -538,6 +880,52 @@ public: break; } + case GET_BUF_RING_MAP: + { + nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA); + int len = reply.get_vendor_data_len(); + wifi_buf_ring_map_entry_t *map(mMaps); + + if (vendor_data == NULL || len == 0) { + ALOGE("No Debug data found"); + return NL_SKIP; + } + + nl_iterator it(vendor_data); + if (it.get_type() == LOGGER_ATTRIBUTE_BUF_RING_NUM) { + unsigned int num_maps = it.get_u32(); + if (*mNumMaps < num_maps) { + ALOGE("Not enough status buffers provided, available: %d required: %d", + *mNumMaps, num_maps); + } else { + *mNumMaps = num_maps; + } + } else { + ALOGE("Unknown attribute: %d expecting %d", + it.get_type(), LOGGER_ATTRIBUTE_BUF_RING_NUM); + return NL_SKIP; + } + + it.next(); + for (unsigned int i = 0; it.has_next() && i < *mNumMaps; it.next()) { + if (it.get_type() == LOGGER_ATTRIBUTE_BUF_RING_MAP) { + if (it.get_len() > sizeof(wifi_buf_ring_map_entry_t)) { + ALOGE("GET_BUF_RING_MAP: unexpected len = %d, dest len = %lu", + it.get_len(), sizeof(wifi_buf_ring_map_entry_t)); + return NL_SKIP; + } else { + memcpy(map, it.get_data(), sizeof(wifi_buf_ring_map_entry_t)); + } + i++; + map++; + } else { + ALOGW("Ignoring invalid attribute type = %d, size = %d", + it.get_type(), it.get_len()); + } + } + break; + } + default: ALOGW("Unknown Debug command"); } @@ -627,6 +1015,8 @@ wifi_error wifi_start_logging(wifi_interface_handle iface, u32 verbose_level, u32 flags, u32 max_interval_sec, u32 min_data_size, char *ring_name) { if (ring_name) { + ALOGE("Ring name: level:%d sec:%d ring_name:%s", + verbose_level, max_interval_sec, ring_name); DebugCommand *cmd = new DebugCommand(iface, verbose_level, flags, max_interval_sec, min_data_size, ring_name, START_RING_LOG); NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); @@ -775,7 +1165,7 @@ wifi_error wifi_set_log_handler(wifi_request_id id, wifi_interface_handle iface, wifi_ring_buffer_data_handler handler) { wifi_handle handle = getWifiHandle(iface); - ALOGV("Loghandler start, handle = %p", handle); + ALOGE("Loghandler start, handle = %p", handle); SetLogHandler *cmd = new SetLogHandler(iface, id, handler); NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); @@ -790,13 +1180,17 @@ wifi_error wifi_set_log_handler(wifi_request_id id, wifi_interface_handle iface, cmd->releaseRef(); return result; } + +#ifdef RING_DUMP + wifi_start_ring_dump(iface, handler); +#endif /* RING_DUMP */ return result; } wifi_error wifi_reset_log_handler(wifi_request_id id, wifi_interface_handle iface) { wifi_handle handle = getWifiHandle(iface); - ALOGV("Loghandler reset, wifi_request_id = %d, handle = %p", id, handle); + ALOGE("Loghandler reset, wifi_request_id = %d, handle = %p", id, handle); if (id == -1) { wifi_ring_buffer_data_handler handler; @@ -806,6 +1200,10 @@ wifi_error wifi_reset_log_handler(wifi_request_id id, wifi_interface_handle ifac NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); cmd->cancel(); cmd->releaseRef(); + +#ifdef RING_DUMP + wifi_stop_ring_dump(iface, handler); +#endif /* RING_DUMP */ return WIFI_SUCCESS; } @@ -1171,6 +1569,338 @@ class HalInit : public WifiCommand } }; +#ifdef RING_DUMP +/////////////////////////////////////////////////////////////////////////////// +class RingDump : public WifiCommand +{ + int mLargestBuffSize; + char *mBuff; + int mErrCode; + int mNumMaps; + wifi_buf_ring_map_entry_t *mMap; + int attr_type_len[DUMP_EVENT_ATTR_MAX]; + char *ring_name[DUMP_BUF_ATTR_MAX]; + wifi_ring_buffer_data_handler mHandle; + +public: + RingDump(wifi_interface_handle iface, int id, int num_maps, wifi_buf_ring_map_entry_t *map, + wifi_ring_buffer_data_handler ring_handle) + : WifiCommand("RingDump", iface, id), mLargestBuffSize(0), mBuff(NULL), + mErrCode(0), mNumMaps(num_maps), mMap(map), mHandle(ring_handle) + { + memset(attr_type_len, 0, sizeof(attr_type_len)); + for (int i = 0; i < DUMP_BUF_ATTR_MAX; i++) { + ring_name[i] = NULL; + } + } + RingDump(wifi_interface_handle iface, int id) + : WifiCommand("RingDump", iface, id), mLargestBuffSize(0), mBuff(NULL), + mErrCode(0) + { + } + + int start() { + DUMP_INFO(("Start Ring Dump Map_cnt:%d\n", mNumMaps)); + registerVendorHandler(GOOGLE_OUI, GOOGLE_FILE_DUMP_EVENT); + + //Set ringname to buf hashmap + for (int i = 0; i < mNumMaps; i++) { + int type = mMap[i].type; + ring_name[type] = (char *)malloc(DBGRING_NAME_MAX); + memset(ring_name[type], 0, DBGRING_NAME_MAX); + memcpy(ring_name[type], mMap[i].ring_name, strlen(mMap[i].ring_name)); + DUMP_DEBUG(("Set ringname Buf:%s Ringname:%s len:%lu", + EWP_CmdAttrToString(type), ring_name[type], strlen(mMap[i].ring_name))); + } + return WIFI_SUCCESS; + } + + virtual int freeup() { + DUMP_DEBUG(("freeup:Enter\n")); + if (mBuff) { + free(mBuff); + mBuff = NULL; + DUMP_INFO(("freed allocated memory\n")); + } + return WIFI_SUCCESS; + } + + virtual int cancel() { + /* unregister file dump handler */ + unregisterVendorHandler(GOOGLE_OUI, GOOGLE_FILE_DUMP_EVENT); + wifi_unregister_cmd(wifiHandle(), id()); + + /* Free up the ring names allocated */ + for (u8 i = 0; i < DUMP_BUF_ATTR_MAX; i++) { + if (ring_name[i]) { + free(ring_name[i]); + ring_name[i] = NULL; + } + } + if (mBuff) { + free(mBuff); + } + + DUMP_INFO(("Stop Ring Dump Successfully Completed, mErrCode = %d\n", mErrCode)); + return WIFI_SUCCESS; + } + + virtual int handleResponse(WifiEvent& reply) { + DUMP_DEBUG(("RingDump::handleResponse\n")); + int buf_attr = DUMP_BUF_ATTR_INVALID; + int len_attr = DUMP_LEN_ATTR_INVALID; + int index = -1; + + if (reply.get_cmd() != NL80211_CMD_VENDOR) { + ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); + return NL_SKIP; + } + + nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA); + int len = reply.get_vendor_data_len(); + + if (vendor_data == NULL || len == 0) { + ALOGE("no vendor data in memory dump response; ignoring it"); + return NL_SKIP; + } + + for (nl_iterator it(vendor_data); it.has_next(); it.next()) { + buf_attr = it.get_type(); + switch (buf_attr) { + case DUMP_BUF_ATTR_MEMDUMP: + case DUMP_BUF_ATTR_TIMESTAMP: + case DUMP_BUF_ATTR_ECNTRS: + case DUMP_BUF_ATTR_DHD_DUMP: + case DUMP_BUF_ATTR_EXT_TRAP: + case DUMP_BUF_ATTR_HEALTH_CHK: + case DUMP_BUF_ATTR_COOKIE: + case DUMP_BUF_ATTR_FLOWRING_DUMP: + case DUMP_BUF_ATTR_STATUS_LOG: + case DUMP_BUF_ATTR_RTT_LOG: + case DUMP_BUF_ATTR_PKTID_MAP_LOG: + case DUMP_BUF_ATTR_PKTID_UNMAP_LOG: { + if (it.get_u32()) { + ALOGE("Copying data to userspace failed, status = %d\n", it.get_u32()); + return WIFI_ERROR_UNKNOWN; + } + index = logger_attr_buffer_lookup(buf_attr); + if (index == -1) { + ALOGE("Invalid index. buf attr = %s\n", EWP_CmdAttrToString(buf_attr)); + return WIFI_ERROR_UNKNOWN; + } + len_attr = attr_lookup_tbl[index].attr_type; + if (len_attr == DUMP_EVENT_ATTR_MAX) { + ALOGE("Invalid len attr = %s\n", EWP_EventAttrToString(len_attr)); + return WIFI_ERROR_UNKNOWN; + } + if (!mBuff || attr_type_len[len_attr] <= 0) { + return WIFI_ERROR_UNKNOWN; + } + + if (!ring_name[buf_attr]) { + ALOGE("Not allocated buf attr = %s\n", EWP_CmdAttrToString(buf_attr)); + return WIFI_ERROR_UNKNOWN; + } + DUMP_INFO(("RingDump:: buf_attr:%s size = %d ring_name:%s\n", + EWP_CmdAttrToString(buf_attr), attr_type_len[len_attr], + ring_name[buf_attr])); + if (mHandle.on_ring_buffer_data) { + /* on_ring_buffer_data callback requires status memory + * so should pass status memory */ + wifi_ring_buffer_status status; + memset(&status, 0, sizeof(status)); + /* Skip msg header. Retrieved log */ + (*mHandle.on_ring_buffer_data)(ring_name[buf_attr], mBuff, + attr_type_len[len_attr], &status); + } + if (mBuff) { + memset(mBuff, 0, mLargestBuffSize); + } + break; + } + default: { + DUMP_DEBUG(("Ignoring invalid attribute buf_attr = %d, size = %d", + buf_attr, it.get_len())); + break; + } + } + } + return NL_OK; + } + + virtual int request_logger_dump(WifiRequest& request, + buf_data_t *buf, int len_attr) { + + int result = 0; + int buf_attr = DUMP_BUF_ATTR_INVALID; + int index = -1; + nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); + + index = logger_attr_lookup(len_attr); + if (index == -1) { + ALOGE("Invalid index\n"); + return WIFI_ERROR_UNKNOWN; + } + buf_attr = attr_lookup_tbl[index].buf_attr; + + if (buf_attr != DUMP_BUF_ATTR_INVALID) { + result = request.put(buf_attr, buf, sizeof(buf_data_t)); + if (result != WIFI_SUCCESS) { + ALOGE("Failed to put get memory dump request; result = %d", result); + return result; + } + } else { + ALOGE("Invalid buf attr = %s, index = %d\n", + EWP_CmdAttrToString(buf_attr), index); + return WIFI_ERROR_UNKNOWN; + } + DUMP_INFO(("Trigger get dump for buf attr = %s\n", + EWP_CmdAttrToString(buf_attr))); + + request.attr_end(data); + return result; + } + + virtual int handleEvent(WifiEvent& event) { + mLargestBuffSize = 0; + mBuff = NULL; + memset(attr_type_len, 0, sizeof(attr_type_len)); + u8 i = 0; + int result = 0; + int mActualBuffSize = 0; + int index = -1; + + nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); + int len = event.get_vendor_data_len(); + int event_id = event.get_vendor_subcmd(); + int req_attr_cnt = 0; + int req_attr[DUMP_EVENT_ATTR_MAX]; + int buf_attr = DUMP_BUF_ATTR_INVALID; + + if (vendor_data == NULL || len == 0) { + ALOGE("No Debug data found"); + return NL_SKIP; + } + DUMP_INFO(("Ring Dump handler. Got event: %d", event_id)); + + buf_data_t buf; + + memset(&buf, 0, sizeof(buf_data_t)); + buf.ver = 0; + buf.buf_threshold = 0; + + if (event_id == GOOGLE_FILE_DUMP_EVENT) { + for (nl_iterator it(vendor_data); it.has_next(); it.next()) { + int attr = it.get_type(); + switch (attr) { + case DUMP_LEN_ATTR_MEMDUMP: + case DUMP_LEN_ATTR_TIMESTAMP: + case DUMP_LEN_ATTR_ECNTRS: + case DUMP_LEN_ATTR_DHD_DUMP: + case DUMP_LEN_ATTR_EXT_TRAP: + case DUMP_LEN_ATTR_HEALTH_CHK: + case DUMP_LEN_ATTR_COOKIE: + case DUMP_LEN_ATTR_FLOWRING_DUMP: + case DUMP_LEN_ATTR_STATUS_LOG: + case DUMP_LEN_ATTR_RTT_LOG: + case DUMP_LEN_ATTR_PKTID_MAP_LOG: + case DUMP_LEN_ATTR_PKTID_UNMAP_LOG: { + mActualBuffSize = it.get_u32(); + DUMP_DEBUG(("len attr %s, len %d\n", + EWP_EventAttrToString(attr), mActualBuffSize)); + if (mActualBuffSize > mLargestBuffSize) + mLargestBuffSize = mActualBuffSize; + attr_type_len[attr] = mActualBuffSize; + + /* Store the order in which attributes are received + * so that file dump can be done in the same order + */ + req_attr[req_attr_cnt++] = attr; + break; + } + default: { + ALOGE("Ignoring invalid attribute type = %d, size = %d", + attr, it.get_len()); + break; + } + } + } + /* Allocation for the largest buffer size to use it recursively for other buf attr. */ + if (mLargestBuffSize) { + DUMP_INFO(("Max dump size: %d", mLargestBuffSize)); + mBuff = (char *)malloc(mLargestBuffSize); + if (!mBuff) { + ALOGE("Buffer allocation failed"); + return NL_SKIP; + } + memset(mBuff, 0, mLargestBuffSize); + } + + WifiRequest request(familyId(), ifaceId()); + result = request.create(GOOGLE_OUI, LOGGER_DEBUG_GET_DUMP); + if (result != WIFI_SUCCESS) { + ALOGE("Failed to create get memory dump request; result = %d", result); + freeup(); + goto exit; + } + + /* Requesting logger dump for each received attr */ + for (i = 0; i < req_attr_cnt; i++) { + int attr = req_attr[i]; + + if (attr_type_len[attr] == 0) { + continue; + } + + index = logger_attr_lookup(attr); + buf_attr = attr_lookup_tbl[index].buf_attr; + if (!ring_name[buf_attr]) { + ALOGE("Failed to find ringname index:%d buf_attr:%d", index, buf_attr); + continue; + } + + buf.len = attr_type_len[attr]; + buf.data_buf[0] = mBuff; + DUMP_DEBUG(("buf len = %d, buf ptr= %p for attr = %s\n", + buf.len, buf.data_buf[0], EWP_EventAttrToString(attr))); + result = request_logger_dump(request, &buf, attr); + if (result != WIFI_SUCCESS) { + /* Proceeding further for other attributes */ + ALOGE("Failed to request the logger dump for attr = %s; result = %d", + EWP_EventAttrToString(attr), result); + continue; + } + result = requestResponse(request); + if (result != WIFI_SUCCESS) { + ALOGE("Failed to register get memory dump response for attr = %s; result = %d", + EWP_EventAttrToString(attr), result); + /* Proceeding further for other attributes */ + continue; + } + } + + WifiRequest request2(familyId(), ifaceId()); + result = request2.create(GOOGLE_OUI, LOGGER_FILE_DUMP_DONE_IND); + if (result != WIFI_SUCCESS) { + ALOGE("Failed to trigger dev close; result = %d", result); + freeup(); + goto exit; + } + requestResponse(request2); + freeup(); + } else { + ALOGE("dump event missing dump length attribute"); + return NL_SKIP; + } + exit: + if (result != WIFI_SUCCESS) { + return NL_SKIP; + } + return NL_OK; + } +}; +/////////////////////////////////////////////////////////////////////////////// +#endif /* RING_DUMP */ wifi_error wifi_start_hal(wifi_interface_handle iface) { @@ -1214,6 +1944,52 @@ wifi_error wifi_hal_preInit(wifi_interface_handle iface) return result; } +#ifdef RING_DUMP +wifi_error wifi_start_ring_dump(wifi_interface_handle iface, + wifi_ring_buffer_data_handler ring_handle) +{ + wifi_handle handle = getWifiHandle(iface); + DUMP_INFO(("start ring dump, handle = %p", handle)); + wifi_buf_ring_map_entry_t map[DUMP_BUF_ATTR_MAX]; + unsigned int num_maps = DUMP_BUF_ATTR_MAX; + wifi_error result; + + /* Get mapping table from driver */ + DebugCommand *debug_cmd = new DebugCommand(iface, &num_maps, map, GET_BUF_RING_MAP); + NULL_CHECK_RETURN(debug_cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); + result = (wifi_error)debug_cmd->start(); + debug_cmd->releaseRef(); + + /* Set ringname to corresponding buf attr */ + RingDump *cmd = new RingDump(iface, FILE_DUMP_REQUEST_ID, num_maps, map, ring_handle); + NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); + result = wifi_register_cmd(handle, FILE_DUMP_REQUEST_ID, cmd); + if (result != WIFI_SUCCESS) { + cmd->releaseRef(); + return result; + } + + result = (wifi_error)cmd->start(); + if (result != WIFI_SUCCESS) { + wifi_unregister_cmd(handle, FILE_DUMP_REQUEST_ID); + cmd->releaseRef(); + return result; + } + return result; +} + +wifi_error wifi_stop_ring_dump(wifi_interface_handle iface, + wifi_ring_buffer_data_handler ring_handle) +{ + RingDump *cmd = new RingDump(iface, FILE_DUMP_REQUEST_ID); + NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); + DUMP_INFO(("stop ring dump")); + cmd->cancel(); + cmd->releaseRef(); + return WIFI_SUCCESS; +} +#endif /* RING_DUMP */ + wifi_error wifi_stop_hal(wifi_interface_handle iface) { HalInit *cmd = new HalInit(iface, HAL_START_REQUEST_ID); |