diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 78ac8e2c82a6..c95b054d3d8a 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -78,6 +78,7 @@ #include #include #include +#include #ifdef MSM_PLATFORM #include #endif @@ -167,6 +168,7 @@ #define PANIC_ON_BUG_STR "" #endif +bool g_is_system_reboot_triggered; int wlan_start_ret_val; static DECLARE_COMPLETION(wlan_start_comp); static unsigned int dev_num = 1; @@ -297,8 +299,8 @@ int limit_off_chan_tbl[HDD_MAX_AC][HDD_MAX_OFF_CHAN_ENTRIES] = { { HDD_AC_VO_BIT, HDD_MAX_OFF_CHAN_TIME_FOR_VO }, }; -/* internal function declaration */ struct notifier_block hdd_netdev_notifier; +struct notifier_block system_reboot_notifier; struct sock *cesium_nl_srv_sock; #ifdef FEATURE_WLAN_AUTO_SHUTDOWN @@ -527,6 +529,12 @@ static bool hdd_wait_for_recovery_completion(void) while (cds_is_driver_recovering()) { if (retry == HDD_MOD_EXIT_SSR_MAX_RETRIES/2) hdd_err("Recovery in progress; wait here!!!"); + + if (g_is_system_reboot_triggered) { + hdd_info("System Reboot happening ignore unload!!"); + return false; + } + msleep(1000); if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) { hdd_err("SSR never completed, error"); @@ -545,6 +553,7 @@ static bool hdd_wait_for_recovery_completion(void) return true; } + static int __hdd_netdev_notifier_call(struct notifier_block *nb, unsigned long state, void *data) { @@ -661,6 +670,27 @@ struct notifier_block hdd_netdev_notifier = { .notifier_call = hdd_netdev_notifier_call, }; +static int system_reboot_notifier_call(struct notifier_block *nb, + unsigned long msg_type, void *_unused) +{ + switch (msg_type) { + case SYS_DOWN: + case SYS_HALT: + case SYS_POWER_OFF: + g_is_system_reboot_triggered = true; + hdd_info("reboot, reason: %ld", msg_type); + break; + default: + break; + } + + return NOTIFY_OK; +} + +struct notifier_block system_reboot_notifier = { + .notifier_call = system_reboot_notifier_call, +}; + /* variable to hold the insmod parameters */ static int con_mode; @@ -6577,6 +6607,7 @@ static void hdd_wlan_exit(struct hdd_context *hdd_ctx) hdd_deinit_all_adapters(hdd_ctx, false); } + unregister_reboot_notifier(&system_reboot_notifier); unregister_netdevice_notifier(&hdd_netdev_notifier); hdd_wlan_stop_modules(hdd_ctx, false); @@ -10542,6 +10573,12 @@ int hdd_wlan_startup(struct device *dev) goto err_wiphy_unregister; } + ret = register_reboot_notifier(&system_reboot_notifier); + if (ret) { + hdd_err("Failed to register reboot notifier: %d", ret); + goto err_unregister_netdev; + } + rtnl_held = hdd_hold_rtnl_lock(); ret = hdd_open_interfaces(hdd_ctx, rtnl_held); @@ -10601,9 +10638,11 @@ err_close_adapters: hdd_close_all_adapters(hdd_ctx, rtnl_held); err_release_rtnl_lock: + unregister_reboot_notifier(&system_reboot_notifier); if (rtnl_held) hdd_release_rtnl_lock(); +err_unregister_netdev: unregister_netdevice_notifier(&hdd_netdev_notifier); err_wiphy_unregister: @@ -11924,7 +11963,8 @@ static void __hdd_module_exit(void) return; } - hdd_wait_for_recovery_completion(); + if (!hdd_wait_for_recovery_completion()) + return; qdf_cancel_delayed_work(&hdd_ctx->iface_idle_work);