Ver Fonte

cnss2: Release DMS QMI handle during dms_del_server

DMS server runs in Modem. When Modem SSR happens dms_del_server
gets called. Even after DMS service disconnected, qmi_txn_wait is
still waiting. Release DMS QMI handle in dms_del_server to cancel
pending transaction.

Change-Id: I06ccfba34269dc51288300aa5fa0326842a09e32
CRs-Fixed: 3288808
Naman Padhiar há 2 anos atrás
pai
commit
2e0fe8fe22
5 ficheiros alterados com 44 adições e 0 exclusões
  1. 3 0
      cnss2/debug.c
  2. 1 0
      cnss2/main.c
  3. 1 0
      cnss2/main.h
  4. 34 0
      cnss2/qmi.c
  5. 5 0
      cnss2/qmi.h

+ 3 - 0
cnss2/debug.c

@@ -130,6 +130,9 @@ static int cnss_stats_show_state(struct seq_file *s,
 		case CNSS_QMI_DMS_CONNECTED:
 			seq_puts(s, "DMS_CONNECTED");
 			continue;
+		case CNSS_DMS_DEL_SERVER:
+			seq_puts(s, "DMS_DEL_SERVER");
+			continue;
 		case CNSS_DAEMON_CONNECTED:
 			seq_puts(s, "DAEMON_CONNECTED");
 			continue;

+ 1 - 0
cnss2/main.c

@@ -4248,6 +4248,7 @@ static int cnss_remove(struct platform_device *plat_dev)
 	cnss_dms_deinit(plat_priv);
 	cnss_qmi_deinit(plat_priv);
 	cnss_event_work_deinit(plat_priv);
+	cnss_cancel_dms_work();
 	cnss_remove_sysfs(plat_priv);
 	cnss_unregister_bus_scale(plat_priv);
 	cnss_unregister_esoc(plat_priv);

+ 1 - 0
cnss2/main.h

@@ -322,6 +322,7 @@ enum cnss_driver_state {
 	CNSS_WLAN_HW_DISABLED,
 	CNSS_FS_READY = 25,
 	CNSS_DRIVER_REGISTERED,
+	CNSS_DMS_DEL_SERVER,
 };
 
 struct cnss_recovery_data {

+ 34 - 0
cnss2/qmi.c

@@ -3246,15 +3246,48 @@ static int dms_new_server(struct qmi_handle *qmi_dms,
 					  service->port);
 }
 
+static void cnss_dms_server_exit_work(struct work_struct *work)
+{
+	int ret;
+	struct cnss_plat_data *plat_priv = cnss_get_plat_priv(NULL);
+
+	cnss_dms_deinit(plat_priv);
+
+	cnss_pr_info("QMI DMS Server Exit");
+	clear_bit(CNSS_DMS_DEL_SERVER, &plat_priv->driver_state);
+
+	ret = cnss_dms_init(plat_priv);
+	if (ret < 0)
+		cnss_pr_err("QMI DMS service registraton failed, ret\n", ret);
+}
+
+static DECLARE_WORK(cnss_dms_del_work, cnss_dms_server_exit_work);
+
 static void dms_del_server(struct qmi_handle *qmi_dms,
 			   struct qmi_service *service)
 {
 	struct cnss_plat_data *plat_priv =
 		container_of(qmi_dms, struct cnss_plat_data, qmi_dms);
 
+	if (!plat_priv)
+		return;
+
+	if (test_bit(CNSS_DMS_DEL_SERVER, &plat_priv->driver_state)) {
+		cnss_pr_info("DMS server delete or cnss remove in progress, Ignore server delete: 0x%lx\n",
+			     plat_priv->driver_state);
+		return;
+	}
+
+	set_bit(CNSS_DMS_DEL_SERVER, &plat_priv->driver_state);
 	clear_bit(CNSS_QMI_DMS_CONNECTED, &plat_priv->driver_state);
 	cnss_pr_info("QMI DMS service disconnected, state: 0x%lx\n",
 		     plat_priv->driver_state);
+	schedule_work(&cnss_dms_del_work);
+}
+
+void cnss_cancel_dms_work(void)
+{
+	cancel_work_sync(&cnss_dms_del_work);
 }
 
 static struct qmi_ops qmi_dms_ops = {
@@ -3283,6 +3316,7 @@ out:
 
 void cnss_dms_deinit(struct cnss_plat_data *plat_priv)
 {
+	set_bit(CNSS_DMS_DEL_SERVER, &plat_priv->driver_state);
 	qmi_handle_release(&plat_priv->qmi_dms);
 }
 

+ 5 - 0
cnss2/qmi.h

@@ -91,6 +91,7 @@ int cnss_wlfw_cal_report_req_send_sync(struct cnss_plat_data *plat_priv,
 int cnss_send_subsys_restart_level_msg(struct cnss_plat_data *plat_priv);
 int cnss_wlfw_ini_file_send_sync(struct cnss_plat_data *plat_priv,
 				 enum wlfw_ini_file_type_v01 file_type);
+void cnss_cancel_dms_work(void);
 #else
 #define QMI_WLFW_TIMEOUT_MS		10000
 
@@ -318,6 +319,10 @@ int cnss_wlfw_ini_file_send_sync(struct cnss_plat_data *plat_priv,
 {
 	return 0;
 }
+
+static void cnss_cancel_dms_work(void)
+{
+}
 #endif /* CONFIG_CNSS2_QMI */
 
 #ifdef CONFIG_CNSS2_DEBUG