summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArunk Khandavalli <akhandav@codeaurora.org>2017-08-23 15:16:55 +0530
committersnandini <snandini@codeaurora.org>2017-08-30 03:48:29 -0700
commit4a4a5e65a5fdd8548bcd35fdcacf351f466d37fa (patch)
treef613b7b61b4756807feac7ed63e5093bcc92d328
parent9512d679f00910ffabb14d9cae1be24a58746fb0 (diff)
qcacld-3.0: Block interface up when recovery is in progress
In certain cases during the SSR/PDR after shutdown the interface up of the driver can be invoked before complete recovery is completed. This can lead to accessing the bus which is not clocked or other issues. Block the interface up from the upper layer until the recovery is completed. CRs-Fixed: 2096446 Change-Id: I6b6569a10520d58e005e56046288ccc10592f725
-rw-r--r--core/hdd/src/wlan_hdd_main.c59
1 files changed, 38 insertions, 21 deletions
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index 1e15a56240c5..88ed006012e4 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -383,6 +383,40 @@ int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
return 0;
}
+/**
+ * hdd_wait_for_recovery_completion() - Wait for cds recovery completion
+ *
+ * Block the unloading of the driver (or) interface up until the
+ * cds recovery is completed
+ *
+ * Return: true for recovery completion else false
+ */
+static bool hdd_wait_for_recovery_completion(void)
+{
+ int retry = 0;
+
+ /* Wait for recovery to complete */
+ while (cds_is_driver_recovering()) {
+ if (retry == HDD_MOD_EXIT_SSR_MAX_RETRIES/2)
+ hdd_err("Recovery in progress; wait here!!!");
+ msleep(1000);
+ if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
+ hdd_err("SSR never completed, error");
+ /*
+ * Trigger the bug_on in the internal builds, in the
+ * customer builds self-recovery will be enabled
+ * in those cases just return error.
+ */
+ if (cds_is_self_recovery_enabled())
+ return false;
+ QDF_BUG(0);
+ }
+ }
+
+ hdd_info("Recovery completed successfully!");
+ return true;
+}
+
static int __hdd_netdev_notifier_call(struct notifier_block *nb,
unsigned long state, void *data)
{
@@ -2171,6 +2205,10 @@ static int __hdd_open(struct net_device *dev)
return -EBUSY;
}
+ if (!hdd_wait_for_recovery_completion()) {
+ hdd_err("Recovery failed");
+ return -EIO;
+ }
mutex_lock(&hdd_init_deinit_lock);
/*
@@ -11206,27 +11244,6 @@ err_dev_state:
return ret;
}
-/**
- * hdd_wait_for_recovery_completion() - Wait for cds recovery completion
- *
- * Block the unloading of the driver until the cds recovery is completed
- *
- * Return: None
- */
-static void hdd_wait_for_recovery_completion(void)
-{
- int retry = 0;
-
- /* Wait for recovery to complete */
- while (cds_is_driver_recovering()) {
- hdd_err("Recovery in progress; wait here!!!");
- msleep(1000);
- if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
- hdd_err("SSR never completed, error");
- QDF_BUG(0);
- }
- }
-}
/**
* __hdd_module_exit - Module exit helper