Bladeren bron

qcacld-3.0: Propagate error from the hdd to wma in case of failure

When the ready event is received from the firmware, hdd callback
is called to create the pdev and update the capabilties. If
there is any error the error is not propogated back to hdd
which can result in the accessing the invalid memory.

Propagate the status correctly from hdd to wma to resolve this issue.
This will result in the probe failure until the resources are available
or reference leaks are fixed.

Change-Id: I97ec062893216e25e285d95d6bfb5cf3e91a4005
CRs-Fixed: 2426612
Arun Kumar Khandavalli 6 jaren geleden
bovenliggende
commit
a423458219
5 gewijzigde bestanden met toevoegingen van 49 en 19 verwijderingen
  1. 0 1
      core/cds/src/cds_api.c
  2. 1 1
      core/hdd/inc/wlan_hdd_cfg.h
  3. 25 9
      core/hdd/src/wlan_hdd_main.c
  4. 1 1
      core/wma/inc/wma_types.h
  5. 22 7
      core/wma/src/wma_main.c

+ 0 - 1
core/cds/src/cds_api.c

@@ -827,7 +827,6 @@ QDF_STATUS cds_pre_enable(void)
 	status = wma_wait_for_ready_event(gp_cds_context->wma_context);
 	status = wma_wait_for_ready_event(gp_cds_context->wma_context);
 	if (QDF_IS_STATUS_ERROR(status)) {
 	if (QDF_IS_STATUS_ERROR(status)) {
 		cds_err("Failed to wait for ready event; status: %u", status);
 		cds_err("Failed to wait for ready event; status: %u", status);
-		cds_trigger_recovery(QDF_REASON_UNSPECIFIED);
 		goto stop_wmi;
 		goto stop_wmi;
 	}
 	}
 
 

+ 1 - 1
core/hdd/inc/wlan_hdd_cfg.h

@@ -299,7 +299,7 @@ QDF_STATUS hdd_set_idle_ps_config(struct hdd_context *hdd_ctx, bool val);
 void hdd_get_pmkid_modes(struct hdd_context *hdd_ctx,
 void hdd_get_pmkid_modes(struct hdd_context *hdd_ctx,
 			 struct pmkid_mode_bits *pmkid_modes);
 			 struct pmkid_mode_bits *pmkid_modes);
 
 
-void hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg);
+int hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg);
 
 
 /**
 /**
  * hdd_string_to_u8_array() - used to convert decimal string into u8 array
  * hdd_string_to_u8_array() - used to convert decimal string into u8 array

+ 25 - 9
core/hdd/src/wlan_hdd_main.c

@@ -1793,7 +1793,7 @@ static void hdd_update_vhtcap_2g(struct hdd_context *hdd_ctx)
 	}
 	}
 }
 }
 
 
-void hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg)
+int hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg)
 {
 {
 	int ret;
 	int ret;
 	struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
 	struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
@@ -1810,12 +1810,12 @@ void hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg)
 
 
 	if (!hdd_ctx) {
 	if (!hdd_ctx) {
 		hdd_err("HDD context is NULL");
 		hdd_err("HDD context is NULL");
-		return;
+		return -EINVAL;
 	}
 	}
 	ret = hdd_objmgr_create_and_store_pdev(hdd_ctx);
 	ret = hdd_objmgr_create_and_store_pdev(hdd_ctx);
 	if (ret) {
 	if (ret) {
 		QDF_DEBUG_PANIC("Failed to create pdev; errno:%d", ret);
 		QDF_DEBUG_PANIC("Failed to create pdev; errno:%d", ret);
-		return;
+		return -EINVAL;
 	}
 	}
 
 
 	hdd_debug("New pdev has been created with pdev_id = %u",
 	hdd_debug("New pdev has been created with pdev_id = %u",
@@ -1825,15 +1825,18 @@ void hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg)
 	if (QDF_IS_STATUS_ERROR(status)) {
 	if (QDF_IS_STATUS_ERROR(status)) {
 		QDF_DEBUG_PANIC("dispatcher pdev open failed; status:%d",
 		QDF_DEBUG_PANIC("dispatcher pdev open failed; status:%d",
 				status);
 				status);
-		return;
+		ret = qdf_status_to_os_return(status);
+		goto exit;
 	}
 	}
 
 
 	status = hdd_component_pdev_open(hdd_ctx->pdev);
 	status = hdd_component_pdev_open(hdd_ctx->pdev);
 	if (QDF_IS_STATUS_ERROR(status)) {
 	if (QDF_IS_STATUS_ERROR(status)) {
 		QDF_DEBUG_PANIC("hdd component pdev open failed; status:%d",
 		QDF_DEBUG_PANIC("hdd component pdev open failed; status:%d",
 				status);
 				status);
-		return;
+		ret = qdf_status_to_os_return(status);
+		goto dispatcher_close;
 	}
 	}
+
 	cdp_pdev_set_ctrl_pdev(cds_get_context(QDF_MODULE_ID_SOC),
 	cdp_pdev_set_ctrl_pdev(cds_get_context(QDF_MODULE_ID_SOC),
 			cds_get_context(QDF_MODULE_ID_TXRX),
 			cds_get_context(QDF_MODULE_ID_TXRX),
 			(struct cdp_ctrl_objmgr_pdev *)hdd_ctx->pdev);
 			(struct cdp_ctrl_objmgr_pdev *)hdd_ctx->pdev);
@@ -1856,7 +1859,8 @@ void hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg)
 						 &sub_20_chan_width);
 						 &sub_20_chan_width);
 	if (QDF_IS_STATUS_ERROR(status)) {
 	if (QDF_IS_STATUS_ERROR(status)) {
 		hdd_err("Failed to get sub_20_chan_width config");
 		hdd_err("Failed to get sub_20_chan_width config");
-		return;
+		ret = qdf_status_to_os_return(status);
+		goto pdev_close;
 	}
 	}
 
 
 	if (cds_cfg) {
 	if (cds_cfg) {
@@ -1873,7 +1877,8 @@ void hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg)
 	status = ucfg_mlme_get_band_capability(hdd_ctx->psoc, &band_capability);
 	status = ucfg_mlme_get_band_capability(hdd_ctx->psoc, &band_capability);
 	if (QDF_IS_STATUS_ERROR(status)) {
 	if (QDF_IS_STATUS_ERROR(status)) {
 		hdd_err("Failed to get MLME band capability");
 		hdd_err("Failed to get MLME band capability");
-		return;
+		ret = qdf_status_to_os_return(status);
+		goto pdev_close;
 	}
 	}
 
 
 	/* first store the INI band capability */
 	/* first store the INI band capability */
@@ -1902,7 +1907,8 @@ void hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg)
 	status = ucfg_mlme_set_band_capability(hdd_ctx->psoc, band_capability);
 	status = ucfg_mlme_set_band_capability(hdd_ctx->psoc, band_capability);
 	if (QDF_IS_STATUS_ERROR(status)) {
 	if (QDF_IS_STATUS_ERROR(status)) {
 		hdd_err("Failed to set MLME Band Capability");
 		hdd_err("Failed to set MLME Band Capability");
-		return;
+		ret = qdf_status_to_os_return(status);
+		goto pdev_close;
 	}
 	}
 
 
 	hdd_ctx->curr_band = band_capability;
 	hdd_ctx->curr_band = band_capability;
@@ -1910,7 +1916,7 @@ void hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg)
 	status = wlan_hdd_update_wiphy_supported_band(hdd_ctx);
 	status = wlan_hdd_update_wiphy_supported_band(hdd_ctx);
 	if (QDF_IS_STATUS_ERROR(status)) {
 	if (QDF_IS_STATUS_ERROR(status)) {
 		hdd_err("Failed to update wiphy band info");
 		hdd_err("Failed to update wiphy band info");
-		return;
+		goto pdev_close;
 	}
 	}
 
 
 	if (!cds_is_driver_recovering() || cds_is_driver_in_bad_state()) {
 	if (!cds_is_driver_recovering() || cds_is_driver_in_bad_state()) {
@@ -2069,6 +2075,16 @@ void hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg)
 	else
 	else
 		hdd_debug("bcast twt is disable in ini, fw cap %d",
 		hdd_debug("bcast twt is disable in ini, fw cap %d",
 			  cfg->bcast_twt_support);
 			  cfg->bcast_twt_support);
+	return 0;
+
+dispatcher_close:
+	dispatcher_pdev_close(hdd_ctx->pdev);
+pdev_close:
+	hdd_component_pdev_close(hdd_ctx->pdev);
+exit:
+	hdd_objmgr_release_and_destroy_pdev(hdd_ctx);
+
+	return ret;
 }
 }
 
 
 bool hdd_dfs_indicate_radar(struct hdd_context *hdd_ctx)
 bool hdd_dfs_indicate_radar(struct hdd_context *hdd_ctx)

+ 1 - 1
core/wma/inc/wma_types.h

@@ -599,7 +599,7 @@ typedef QDF_STATUS (*wma_tx_ota_comp_callback)(void *context, qdf_nbuf_t buf,
 				      uint32_t status, void *params);
 				      uint32_t status, void *params);
 
 
 /* generic callback for updating parameters from target to HDD */
 /* generic callback for updating parameters from target to HDD */
-typedef void (*wma_tgt_cfg_cb)(hdd_handle_t handle, struct wma_tgt_cfg *cfg);
+typedef int (*wma_tgt_cfg_cb)(hdd_handle_t handle, struct wma_tgt_cfg *cfg);
 
 
 /**
 /**
  * struct wma_cli_set_cmd_t - set command parameters
  * struct wma_cli_set_cmd_t - set command parameters

+ 22 - 7
core/wma/src/wma_main.c

@@ -5605,9 +5605,9 @@ wma_fill_chain_cfg(struct target_psoc_info *tgt_hdl,
  * wma_update_hdd_cfg() - update HDD config
  * wma_update_hdd_cfg() - update HDD config
  * @wma_handle: wma handle
  * @wma_handle: wma handle
  *
  *
- * Return: none
+ * Return: Zero on success err number on failure
  */
  */
-static void wma_update_hdd_cfg(tp_wma_handle wma_handle)
+static int wma_update_hdd_cfg(tp_wma_handle wma_handle)
 {
 {
 	struct wma_tgt_cfg tgt_cfg;
 	struct wma_tgt_cfg tgt_cfg;
 	void *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
 	void *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
@@ -5616,26 +5616,28 @@ static void wma_update_hdd_cfg(tp_wma_handle wma_handle)
 	struct target_psoc_info *tgt_hdl;
 	struct target_psoc_info *tgt_hdl;
 	struct wmi_unified *wmi_handle;
 	struct wmi_unified *wmi_handle;
 	uint8_t i;
 	uint8_t i;
+	int ret;
 
 
 	WMA_LOGD("%s: Enter", __func__);
 	WMA_LOGD("%s: Enter", __func__);
 
 
 	tgt_hdl = wlan_psoc_get_tgt_if_handle(wma_handle->psoc);
 	tgt_hdl = wlan_psoc_get_tgt_if_handle(wma_handle->psoc);
 	if (!tgt_hdl) {
 	if (!tgt_hdl) {
 		WMA_LOGE("%s: target psoc info is NULL", __func__);
 		WMA_LOGE("%s: target psoc info is NULL", __func__);
-		return;
+		return -EINVAL;
 	}
 	}
 
 
 	wlan_res_cfg = target_psoc_get_wlan_res_cfg(tgt_hdl);
 	wlan_res_cfg = target_psoc_get_wlan_res_cfg(tgt_hdl);
 	if (!wlan_res_cfg) {
 	if (!wlan_res_cfg) {
 		WMA_LOGE("%s: wlan_res_cfg is null", __func__);
 		WMA_LOGE("%s: wlan_res_cfg is null", __func__);
-		return;
+		return -EINVAL;
 	}
 	}
+
 	service_ext_param =
 	service_ext_param =
 			target_psoc_get_service_ext_param(tgt_hdl);
 			target_psoc_get_service_ext_param(tgt_hdl);
 	wmi_handle = get_wmi_unified_hdl_from_psoc(wma_handle->psoc);
 	wmi_handle = get_wmi_unified_hdl_from_psoc(wma_handle->psoc);
 	if (!wmi_handle) {
 	if (!wmi_handle) {
 		WMA_LOGE("%s: wmi handle is NULL", __func__);
 		WMA_LOGE("%s: wmi handle is NULL", __func__);
-		return;
+		return -EINVAL;
 	}
 	}
 
 
 	qdf_mem_zero(&tgt_cfg, sizeof(struct wma_tgt_cfg));
 	qdf_mem_zero(&tgt_cfg, sizeof(struct wma_tgt_cfg));
@@ -5711,11 +5713,15 @@ static void wma_update_hdd_cfg(tp_wma_handle wma_handle)
 	for (i = 0; i < tgt_hdl->info.total_mac_phy_cnt; i++)
 	for (i = 0; i < tgt_hdl->info.total_mac_phy_cnt; i++)
 		wma_fill_chain_cfg(tgt_hdl, i);
 		wma_fill_chain_cfg(tgt_hdl, i);
 
 
-	wma_handle->tgt_cfg_update_cb(hdd_ctx, &tgt_cfg);
+	ret = wma_handle->tgt_cfg_update_cb(hdd_ctx, &tgt_cfg);
+	if (ret)
+		return -EINVAL;
 	target_if_store_pdev_target_if_ctx(wma_get_pdev_from_scn_handle);
 	target_if_store_pdev_target_if_ctx(wma_get_pdev_from_scn_handle);
 	target_pdev_set_wmi_handle(wma_handle->pdev->tgt_if_handle,
 	target_pdev_set_wmi_handle(wma_handle->pdev->tgt_if_handle,
 				   wma_handle->wmi_handle);
 				   wma_handle->wmi_handle);
 	wma_green_ap_register_handlers(wma_handle);
 	wma_green_ap_register_handlers(wma_handle);
+
+	return ret;
 }
 }
 
 
 /**
 /**
@@ -6820,6 +6826,7 @@ int wma_rx_ready_event(void *handle, uint8_t *cmd_param_info,
 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
 	tp_wma_handle wma_handle = (tp_wma_handle) handle;
 	WMI_READY_EVENTID_param_tlvs *param_buf = NULL;
 	WMI_READY_EVENTID_param_tlvs *param_buf = NULL;
 	wmi_ready_event_fixed_param *ev = NULL;
 	wmi_ready_event_fixed_param *ev = NULL;
+	int ret;
 
 
 	WMA_LOGD("%s: Enter", __func__);
 	WMA_LOGD("%s: Enter", __func__);
 
 
@@ -6848,7 +6855,10 @@ int wma_rx_ready_event(void *handle, uint8_t *cmd_param_info,
 	/* copy the mac addr */
 	/* copy the mac addr */
 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->mac_addr, wma_handle->myaddr);
 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->mac_addr, wma_handle->myaddr);
 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->mac_addr, wma_handle->hwaddr);
 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->mac_addr, wma_handle->hwaddr);
-	wma_update_hdd_cfg(wma_handle);
+	ret = wma_update_hdd_cfg(wma_handle);
+	if (ret)
+		return ret;
+
 	WMA_LOGD("Exit");
 	WMA_LOGD("Exit");
 
 
 	return 0;
 	return 0;
@@ -6920,6 +6930,11 @@ QDF_STATUS wma_wait_for_ready_event(WMA_HANDLE handle)
 
 
 	status = qdf_wait_for_event_completion(&tgt_hdl->info.event,
 	status = qdf_wait_for_event_completion(&tgt_hdl->info.event,
 					       WMA_READY_EVENTID_TIMEOUT);
 					       WMA_READY_EVENTID_TIMEOUT);
+	if (!tgt_hdl->info.wmi_ready) {
+		wma_err("Error in pdev creation");
+		return QDF_STATUS_E_INVAL;
+	}
+
 	if (status == QDF_STATUS_E_TIMEOUT)
 	if (status == QDF_STATUS_E_TIMEOUT)
 		wma_err("Timeout waiting for FW ready event");
 		wma_err("Timeout waiting for FW ready event");
 	else if (QDF_IS_STATUS_ERROR(status))
 	else if (QDF_IS_STATUS_ERROR(status))