Parcourir la source

msm: ipa: Fix ipa_pre_init teardown

Part of allocations made by the ipa_pre_init() are not freed correctly.
Fixing this by calling the relevant cleanup's.
Since the ipa_odl_init() is not the last allocation now,
the appropriate ipa_odl_cleanup added.

Change-Id: Iedbe1dff829f5bedbf788ffd89928982a498d065
Signed-off-by: Ilia Lin <[email protected]>
Ilia Lin il y a 4 ans
Parent
commit
7e89bf0760

+ 27 - 3
drivers/platform/msm/ipa/ipa_v3/ipa.c

@@ -6574,6 +6574,12 @@ static inline void ipa3_enable_napi_netdev(void)
 	}
 }
 
+static inline void ipa3_disable_napi_netdev(void)
+{
+	if (ipa3_ctx->lan_rx_napi_enable)
+		netif_napi_del(&ipa3_ctx->napi_lan_rx);
+}
+
 static u32 get_tx_wrapper_cache_size(u32 cache_size)
 {
 	if (cache_size <= IPA_TX_WRAPPER_CACHE_MAX_THRESHOLD)
@@ -7148,7 +7154,7 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
 		if (result) {
 			IPADBG("Error: ODL init fialed\n");
 			result = -ENODEV;
-			goto fail_cdev_add;
+			goto fail_odl_init;
 		}
 	}
 
@@ -7164,14 +7170,32 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
 	/* Create the dummy netdev for LAN RX NAPI*/
 	ipa3_enable_napi_netdev();
 
-	ipa3_wwan_init();
+	result = ipa3_wwan_init();
+	if (result) {
+		IPAERR(":ipa3_wwan_init err=%d\n", -result);
+		result = -ENODEV;
+		goto fail_wwan_init;
+	}
 
-	ipa3_rmnet_ctl_init();
+	result = ipa3_rmnet_ctl_init();
+	if (result) {
+		IPAERR(":ipa3_rmnet_ctl_init err=%d\n", -result);
+		result = -ENODEV;
+		goto fail_rmnet_ctl_init;
+	}
 
 	mutex_init(&ipa3_ctx->app_clock_vote.mutex);
 
 	return 0;
 
+fail_rmnet_ctl_init:
+	ipa3_wwan_cleanup();
+fail_wwan_init:
+	ipa3_disable_napi_netdev();
+	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_1)
+		ipa_odl_cleanup();
+fail_odl_init:
+	cdev_del(cdev);
 fail_cdev_add:
 fail_gsi_pre_fw_load_init:
 	ipa3_dma_shutdown();

+ 20 - 0
drivers/platform/msm/ipa/ipa_v3/ipa_odl.c

@@ -771,6 +771,26 @@ fail_mem_ctx:
 	return result;
 }
 
+void ipa_odl_cleanup(void)
+{
+	struct ipa3_odl_char_device_context *odl_cdev;
+
+	if (!ipa3_odl_ctx)
+		return;
+
+	odl_cdev = ipa3_odl_ctx->odl_cdev;
+
+	ipa_pm_deregister(ipa3_odl_ctx->odl_pm_hdl);
+	device_destroy(odl_cdev[1].class, odl_cdev[1].dev_num);
+	unregister_chrdev_region(odl_cdev[1].dev_num, 1);
+	class_destroy(odl_cdev[1].class);
+	device_destroy(odl_cdev[0].class, odl_cdev[0].dev_num);
+	unregister_chrdev_region(odl_cdev[0].dev_num, 1);
+	class_destroy(odl_cdev[0].class);
+	kfree(ipa3_odl_ctx);
+	ipa3_odl_ctx = NULL;
+}
+
 bool ipa3_is_odl_connected(void)
 {
 	return ipa3_odl_ctx->odl_state.odl_connected;

+ 1 - 0
drivers/platform/msm/ipa/ipa_v3/ipa_odl.h

@@ -69,6 +69,7 @@ struct ipa3_push_msg_odl {
 extern struct ipa_odl_context *ipa3_odl_ctx;
 
 int ipa_odl_init(void);
+void ipa_odl_cleanup(void);
 void ipa3_odl_pipe_cleanup(bool is_ssr);
 int ipa3_odl_pipe_open(void);