qcacmn: Free serial cmd before its timer when rmmod
Rmmod process:
wlan_hdd_pld_remove --> hdd_stop_adapter --> hdd_vdev_destroy
--> WLAN_SER_CMD_DEL_STA_SESSION (25) cmd queued --> PLD_FW_DOWN
(will complete wait event as part of qdf_complete_wait_events)
--> hdd_wlan_stop_modules --> cds_disable -->
dispatcher_psoc_disable --> wlan_serialization_psoc_disable -->
wlan_serialization_timer_destroy --> umac_stop --> csr_stop -->
wlan_ser_cancel_non_scan_cmd -> check if timer is present but th
timer are already destroyed, so assert.
Move wlan_serialization_purge_cmd_list into converged API file to
be shared by MCC and WIN.
Change-Id: Iad557e4a05d682c257be0c39049c52950e5eb530
CRs-Fixed: 2451058
diff --git a/umac/cmn_services/serialization/inc/wlan_serialization_api.h b/umac/cmn_services/serialization/inc/wlan_serialization_api.h
index a22337c..a7e19d0 100644
--- a/umac/cmn_services/serialization/inc/wlan_serialization_api.h
+++ b/umac/cmn_services/serialization/inc/wlan_serialization_api.h
@@ -604,4 +604,20 @@
wlan_ser_validate_umac_cmd(struct wlan_objmgr_vdev *vdev,
enum wlan_serialization_cmd_type cmd_type,
wlan_ser_umac_cmd_cb umac_cmd_cb);
+
+/**
+ * wlan_serialization_purge_all_pdev_cmd() - purge all command for given pdev
+ * @pdev: objmgr pdev pointer
+ *
+ * Return: void
+ */
+void wlan_serialization_purge_all_pdev_cmd(struct wlan_objmgr_pdev *pdev);
+
+/**
+ * wlan_serialization_purge_all_cmd() - purge all command for psoc
+ * @psoc: objmgr psoc pointer
+ *
+ * Return: void
+ */
+void wlan_serialization_purge_all_cmd(struct wlan_objmgr_psoc *psoc);
#endif
diff --git a/umac/cmn_services/serialization/src/wlan_serialization_api.c b/umac/cmn_services/serialization/src/wlan_serialization_api.c
index de9ae64..bebc087 100644
--- a/umac/cmn_services/serialization/src/wlan_serialization_api.c
+++ b/umac/cmn_services/serialization/src/wlan_serialization_api.c
@@ -781,3 +781,44 @@
return status;
}
+
+void wlan_serialization_purge_all_pdev_cmd(struct wlan_objmgr_pdev *pdev)
+{
+ struct wlan_ser_pdev_obj *ser_pdev_obj;
+
+ if (!pdev) {
+ ser_err("NULL pdev");
+ return;
+ }
+
+ ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev);
+ if (!ser_pdev_obj) {
+ ser_err("invalid ser_pdev_obj");
+ return;
+ }
+
+ wlan_ser_cancel_scan_cmd(ser_pdev_obj, pdev, NULL, NULL,
+ WLAN_SER_CMD_SCAN, false);
+ wlan_ser_cancel_scan_cmd(ser_pdev_obj, pdev, NULL, NULL,
+ WLAN_SER_CMD_SCAN, true);
+ wlan_ser_cancel_non_scan_cmd(ser_pdev_obj, pdev, NULL, NULL,
+ WLAN_SER_CMD_NONSCAN, false);
+ wlan_ser_cancel_non_scan_cmd(ser_pdev_obj, pdev, NULL, NULL,
+ WLAN_SER_CMD_NONSCAN, true);
+}
+
+static inline
+void wlan_ser_purge_pdev_cmd_cb(struct wlan_objmgr_psoc *psoc,
+ void *object, void *arg)
+{
+ struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)object;
+
+ wlan_serialization_purge_all_pdev_cmd(pdev);
+}
+
+void wlan_serialization_purge_all_cmd(struct wlan_objmgr_psoc *psoc)
+{
+ wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
+ wlan_ser_purge_pdev_cmd_cb, NULL, 1,
+ WLAN_SERIALIZATION_ID);
+}
diff --git a/umac/cmn_services/serialization/src/wlan_serialization_main.c b/umac/cmn_services/serialization/src/wlan_serialization_main.c
index dbb7fb3..f663a8d 100644
--- a/umac/cmn_services/serialization/src/wlan_serialization_main.c
+++ b/umac/cmn_services/serialization/src/wlan_serialization_main.c
@@ -41,6 +41,12 @@
ser_err("invalid ser_soc_obj");
goto error;
}
+
+ /*
+ * purge all serialization command if there are any pending to make
+ * sure memory and vdev ref are freed.
+ */
+ wlan_serialization_purge_all_cmd(psoc);
/* clean up all timers before exiting */
status = wlan_serialization_cleanup_all_timers(ser_soc_obj);
if (status != QDF_STATUS_SUCCESS)