Browse Source

Merge "qcacmn: Add objmgr check for pdev leaks API"

Linux Build Service Account 6 years ago
parent
commit
3dcbc895e0

+ 7 - 3
htc/htc_send.c

@@ -633,9 +633,13 @@ static QDF_STATUS htc_issue_packets(HTC_TARGET *target,
 						("hif_send Failed status:%d\n",
 						 status));
 			}
-			qdf_nbuf_unmap(target->osdev,
-				GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket),
-				QDF_DMA_TO_DEVICE);
+
+			/* only unmap if we mapped in this function */
+			if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint))
+				qdf_nbuf_unmap(target->osdev,
+					GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket),
+					QDF_DMA_TO_DEVICE);
+
 			if (!pEndpoint->async_update) {
 				LOCK_HTC_TX(target);
 			}

+ 8 - 0
umac/cmn_services/obj_mgr/inc/wlan_objmgr_psoc_obj.h

@@ -1436,6 +1436,14 @@ QDF_STATUS wlan_objmgr_print_ref_all_objects_per_psoc(
 QDF_STATUS wlan_objmgr_psoc_set_user_config(struct wlan_objmgr_psoc *psoc,
 		struct wlan_objmgr_psoc_user_config *user_config_data);
 
+/**
+ * wlan_objmgr_psoc_check_for_pdev_leaks() - Assert no pdevs attached to @psoc
+ * @psoc: The psoc to check
+ *
+ * Return: None
+ */
+void wlan_objmgr_psoc_check_for_pdev_leaks(struct wlan_objmgr_psoc *psoc);
+
 /**
  * wlan_objmgr_psoc_check_for_vdev_leaks() - Assert no vdevs attached to @psoc
  * @psoc: The psoc to check

+ 49 - 0
umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c

@@ -2005,6 +2005,55 @@ QDF_STATUS wlan_objmgr_psoc_set_user_config(struct wlan_objmgr_psoc *psoc,
 	return QDF_STATUS_SUCCESS;
 }
 
+void wlan_objmgr_psoc_check_for_pdev_leaks(struct wlan_objmgr_psoc *psoc)
+{
+	struct wlan_objmgr_psoc_objmgr *_psoc;
+	int pdev_id;
+	int ref_id;
+
+	QDF_BUG(psoc);
+	if (!psoc)
+		return;
+
+	wlan_psoc_obj_lock(psoc);
+	_psoc = &psoc->soc_objmgr;
+	if (!_psoc->wlan_pdev_count) {
+		wlan_psoc_obj_unlock(psoc);
+		return;
+	}
+
+	obj_mgr_err("objmgr pdev leaks detected for psoc %u!", _psoc->psoc_id);
+	obj_mgr_err("--------------------------------------------------------");
+	obj_mgr_err("Pdev Id   Refs   Module");
+	obj_mgr_err("--------------------------------------------------------");
+
+	for (pdev_id = 0; pdev_id < WLAN_UMAC_MAX_PDEVS; pdev_id++) {
+		struct wlan_objmgr_pdev *pdev = _psoc->wlan_pdev_list[pdev_id];
+		qdf_atomic_t *ref_id_dbg;
+
+		if (!pdev)
+			continue;
+
+		wlan_pdev_obj_lock(pdev);
+		ref_id_dbg = pdev->pdev_objmgr.ref_id_dbg;
+		for (ref_id = 0; ref_id < WLAN_REF_ID_MAX; ref_id++) {
+			int32_t refs = qdf_atomic_read(&ref_id_dbg[ref_id]);
+
+			if (refs <= 0)
+				continue;
+
+			obj_mgr_err("%7u   %4u x %s",
+				    pdev_id, refs, string_from_dbgid(ref_id));
+		}
+		wlan_pdev_obj_unlock(pdev);
+	}
+
+	wlan_psoc_obj_unlock(psoc);
+
+	QDF_DEBUG_PANIC();
+}
+qdf_export_symbol(wlan_objmgr_psoc_check_for_pdev_leaks);
+
 void wlan_objmgr_psoc_check_for_vdev_leaks(struct wlan_objmgr_psoc *psoc)
 {
 	struct wlan_objmgr_psoc_objmgr *_psoc;

+ 2 - 0
umac/scan/core/src/wlan_scan_main.h

@@ -219,10 +219,12 @@ struct pdev_scan_info {
  * struct scan_vdev_obj - scan vdev obj
  * @pno_match_evt_received: pno match received
  * @pno_in_progress: pno in progress
+ * @is_vdev_delete_in_progress: flag to indicate if vdev del is in progress
  */
 struct scan_vdev_obj {
 	bool pno_match_evt_received;
 	bool pno_in_progress;
+	bool is_vdev_delete_in_progress;
 };
 
 /**

+ 27 - 12
umac/scan/core/src/wlan_scan_manager.c

@@ -369,8 +369,9 @@ scm_scan_start_req(struct scheduler_msg *msg)
 {
 	struct wlan_serialization_command cmd = {0, };
 	enum wlan_serialization_status ser_cmd_status;
-	struct scan_start_request *req;
+	struct scan_start_request *req = NULL;
 	struct wlan_scan_obj *scan_obj;
+	struct scan_vdev_obj *scan_vdev_priv_obj;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
 	if (!msg) {
@@ -388,7 +389,8 @@ scm_scan_start_req(struct scheduler_msg *msg)
 	scan_obj = wlan_vdev_get_scan_obj(req->vdev);
 	if (!scan_obj) {
 		scm_debug("Couldn't find scan object");
-		return QDF_STATUS_E_NULL_VALUE;
+		status = QDF_STATUS_E_NULL_VALUE;
+		goto err;
 	}
 
 	cmd.cmd_type = WLAN_SER_CMD_SCAN;
@@ -409,6 +411,18 @@ scm_scan_start_req(struct scheduler_msg *msg)
 		req, req->scan_req.scan_req_id, req->scan_req.scan_id,
 		req->scan_req.vdev_id);
 
+	scan_vdev_priv_obj = wlan_get_vdev_scan_obj(req->vdev);
+	if (!scan_vdev_priv_obj) {
+		scm_debug("Couldn't find scan priv object");
+		status = QDF_STATUS_E_NULL_VALUE;
+		goto err;
+	}
+	if (scan_vdev_priv_obj->is_vdev_delete_in_progress) {
+		scm_err("Can't allow scan on vdev_id:%d",
+			wlan_vdev_get_id(req->vdev));
+		status = QDF_STATUS_E_NULL_VALUE;
+		goto err;
+	}
 	ser_cmd_status = wlan_serialization_request(&cmd);
 	scm_info("wlan_serialization_request status:%d", ser_cmd_status);
 
@@ -427,21 +441,22 @@ scm_scan_start_req(struct scheduler_msg *msg)
 		 */
 		scm_post_internal_scan_complete_event(req,
 				SCAN_REASON_INTERNAL_FAILURE);
-		/* cmd can't be serviced.
-		 * release vdev reference and free scan_start_request memory
-		 */
-		wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
-		scm_scan_free_scan_request_mem(req);
-		break;
+		goto err;
 	default:
 		QDF_ASSERT(0);
 		status = QDF_STATUS_E_INVAL;
-		/* cmd can't be serviced.
-		 * release vdev reference and free scan_start_request memory
-		 */
+		goto err;
+	}
+
+	return status;
+err:
+	/*
+	 * cmd can't be serviced.
+	 * release vdev reference and free scan_start_request memory
+	 */
+	if (req) {
 		wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
 		scm_scan_free_scan_request_mem(req);
-		break;
 	}
 
 	return status;

+ 15 - 0
umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h

@@ -590,4 +590,19 @@ void ucfg_scan_set_bt_activity(struct wlan_objmgr_psoc *psoc,
  * Return: true if enabled else false.
  */
 bool ucfg_scan_get_bt_activity(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * ucfg_scan_set_vdev_del_in_progress() - API to mark vdev delete in progress
+ * @vdev: pointer to vdev object
+ *
+ * Return: none
+ */
+void ucfg_scan_set_vdev_del_in_progress(struct wlan_objmgr_vdev *vdev);
+/**
+ * ucfg_scan_clear_vdev_del_in_progress() - API to reset vdev delete in progress
+ * @vdev: pointer to vdev object
+ *
+ * Return: none
+ */
+void ucfg_scan_clear_vdev_del_in_progress(struct wlan_objmgr_vdev *vdev);
 #endif

+ 32 - 0
umac/scan/dispatcher/src/wlan_scan_ucfg_api.c

@@ -2178,6 +2178,38 @@ bool ucfg_scan_get_bt_activity(struct wlan_objmgr_psoc *psoc)
 	return scan_obj->bt_a2dp_enabled;
 }
 
+void ucfg_scan_set_vdev_del_in_progress(struct wlan_objmgr_vdev *vdev)
+{
+	struct scan_vdev_obj *scan_vdev_obj;
+
+	if (!vdev) {
+		scm_err("invalid vdev");
+		return;
+	}
+	scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
+	if (!scan_vdev_obj) {
+		scm_err("null scan_vdev_obj");
+		return;
+	}
+	scan_vdev_obj->is_vdev_delete_in_progress = true;
+}
+
+void ucfg_scan_clear_vdev_del_in_progress(struct wlan_objmgr_vdev *vdev)
+{
+	struct scan_vdev_obj *scan_vdev_obj;
+
+	if (!vdev) {
+		scm_err("invalid vdev");
+		return;
+	}
+	scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
+	if (!scan_vdev_obj) {
+		scm_err("null scan_vdev_obj");
+		return;
+	}
+	scan_vdev_obj->is_vdev_delete_in_progress = false;
+}
+
 QDF_STATUS
 ucfg_scan_set_global_config(struct wlan_objmgr_psoc *psoc,
 			       enum scan_config config, uint32_t val)

+ 1 - 1
wmi/src/wmi_unified_tlv.c

@@ -9294,7 +9294,7 @@ static QDF_STATUS send_stats_ext_req_cmd_tlv(wmi_unified_t wmi_handle,
 	QDF_STATUS ret;
 	wmi_req_stats_ext_cmd_fixed_param *cmd;
 	wmi_buf_t buf;
-	uint16_t len;
+	size_t len;
 	uint8_t *buf_ptr;
 
 	len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + preq->request_data_len;