static void ath12k_core_stop(struct ath12k_base *ab)
 {
+       ath12k_core_stopped(ab);
+
        if (!test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags))
                ath12k_qmi_firmware_stop(ab);
 
 {
        int ret;
 
+       lockdep_assert_held(&ab->core_lock);
+
        ret = ath12k_wmi_attach(ab);
        if (ret) {
                ath12k_err(ab, "failed to attach wmi: %d\n", ret);
                /* ACPI is optional so continue in case of an error */
                ath12k_dbg(ab, ATH12K_DBG_BOOT, "acpi failed: %d\n", ret);
 
+       if (!test_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags))
+               /* Indicate the core start in the appropriate group */
+               ath12k_core_started(ab);
+
        return 0;
 
 err_reo_cleanup:
        return ret;
 }
 
+static void ath12k_core_device_cleanup(struct ath12k_base *ab)
+{
+       mutex_lock(&ab->core_lock);
+
+       ath12k_hif_irq_disable(ab);
+       ath12k_core_pdev_destroy(ab);
+       ath12k_mac_unregister(ab);
+       ath12k_mac_destroy(ab);
+
+       mutex_unlock(&ab->core_lock);
+}
+
+static void ath12k_core_hw_group_stop(struct ath12k_hw_group *ag)
+{
+       struct ath12k_base *ab;
+       int i;
+
+       lockdep_assert_held(&ag->mutex);
+
+       for (i = ag->num_devices - 1; i >= 0; i--) {
+               ab = ag->ab[i];
+               if (!ab)
+                       continue;
+               ath12k_core_device_cleanup(ab);
+       }
+}
+
+static int ath12k_core_hw_group_start(struct ath12k_hw_group *ag)
+{
+       struct ath12k_base *ab;
+       int ret, i;
+
+       lockdep_assert_held(&ag->mutex);
+
+       for (i = 0; i < ag->num_devices; i++) {
+               ab = ag->ab[i];
+               if (!ab)
+                       continue;
+
+               mutex_lock(&ab->core_lock);
+
+               /* Check if already registered or not, since same flow
+                * execute for HW restart case.
+                */
+               if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags))
+                       goto core_pdev_create;
+
+               ret = ath12k_mac_allocate(ab);
+               if (ret) {
+                       ath12k_err(ab, "failed to create new hw device with mac80211 :%d\n",
+                                  ret);
+                       mutex_unlock(&ab->core_lock);
+                       return ret;
+               }
+
+               ret = ath12k_mac_register(ab);
+               if (ret) {
+                       ath12k_err(ab, "failed to register radio with mac80211: %d\n",
+                                  ret);
+                       mutex_unlock(&ab->core_lock);
+                       goto err;
+               }
+
+core_pdev_create:
+               ret = ath12k_core_pdev_create(ab);
+               if (ret) {
+                       ath12k_err(ab, "failed to create pdev core %d\n", ret);
+                       mutex_unlock(&ab->core_lock);
+                       goto err;
+               }
+
+               ath12k_hif_irq_enable(ab);
+
+               ret = ath12k_core_rfkill_config(ab);
+               if (ret && ret != -EOPNOTSUPP) {
+                       mutex_unlock(&ab->core_lock);
+                       goto err;
+               }
+
+               mutex_unlock(&ab->core_lock);
+       }
+
+       return 0;
+
+err:
+       ath12k_core_hw_group_stop(ag);
+
+       return ret;
+}
+
 static int ath12k_core_start_firmware(struct ath12k_base *ab,
                                      enum ath12k_firmware_mode mode)
 {
        return ret;
 }
 
+static inline
+bool ath12k_core_hw_group_start_ready(struct ath12k_hw_group *ag)
+{
+       lockdep_assert_held(&ag->mutex);
+
+       return (ag->num_started == ag->num_devices);
+}
+
 int ath12k_core_qmi_firmware_ready(struct ath12k_base *ab)
 {
-       int ret;
+       struct ath12k_hw_group *ag = ath12k_ab_to_ag(ab);
+       int ret, i;
 
        ret = ath12k_core_start_firmware(ab, ATH12K_FIRMWARE_MODE_NORMAL);
        if (ret) {
                goto err_firmware_stop;
        }
 
+       mutex_lock(&ag->mutex);
        mutex_lock(&ab->core_lock);
+
        ret = ath12k_core_start(ab, ATH12K_FIRMWARE_MODE_NORMAL);
        if (ret) {
                ath12k_err(ab, "failed to start core: %d\n", ret);
                goto err_dp_free;
        }
 
-       ret = ath12k_mac_allocate(ab);
-       if (ret) {
-               ath12k_err(ab, "failed to create new hw device with mac80211 :%d\n",
-                          ret);
-               goto err_core_stop;
-       }
-
-       ret = ath12k_mac_register(ab);
-       if (ret) {
-               ath12k_err(ab, "failed register the radio with mac80211: %d\n", ret);
-               goto err_mac_destroy;
-       }
-
-       ret = ath12k_core_pdev_create(ab);
-       if (ret) {
-               ath12k_err(ab, "failed to create pdev core: %d\n", ret);
-               goto err_mac_unregister;
-       }
-
-       ath12k_hif_irq_enable(ab);
+       mutex_unlock(&ab->core_lock);
 
-       ret = ath12k_core_rfkill_config(ab);
-       if (ret && ret != -EOPNOTSUPP) {
-               ath12k_err(ab, "failed to config rfkill: %d\n", ret);
-               goto err_hif_irq_disable;
+       if (ath12k_core_hw_group_start_ready(ag)) {
+               ret = ath12k_core_hw_group_start(ag);
+               if (ret) {
+                       ath12k_warn(ab, "unable to start hw group\n");
+                       goto err_core_stop;
+               }
+               ath12k_dbg(ab, ATH12K_DBG_BOOT, "group %d started\n", ag->id);
        }
 
-       mutex_unlock(&ab->core_lock);
+       mutex_unlock(&ag->mutex);
 
        return 0;
 
-err_hif_irq_disable:
-       ath12k_hif_irq_disable(ab);
-       ath12k_core_pdev_destroy(ab);
-err_mac_unregister:
-       ath12k_mac_unregister(ab);
-err_mac_destroy:
-       ath12k_mac_destroy(ab);
 err_core_stop:
-       ath12k_core_stop(ab);
+       for (i = ag->num_devices - 1; i >= 0; i--) {
+               ab = ag->ab[i];
+               if (!ab)
+                       continue;
+
+               mutex_lock(&ab->core_lock);
+               ath12k_core_stop(ab);
+               mutex_unlock(&ab->core_lock);
+       }
+       goto exit;
+
 err_dp_free:
        ath12k_dp_free(ab);
        mutex_unlock(&ab->core_lock);
 err_firmware_stop:
        ath12k_qmi_firmware_stop(ab);
 
+exit:
+       mutex_unlock(&ag->mutex);
        return ret;
 }
 
        }
 
        if (ab->is_reset) {
+               if (!test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags)) {
+                       atomic_dec(&ab->reset_count);
+                       complete(&ab->reset_complete);
+                       ab->is_reset = false;
+                       atomic_set(&ab->fail_cont_count, 0);
+                       ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset success\n");
+               }
+
                for (i = 0; i < ath12k_get_num_hw(ab); i++) {
                        ah = ath12k_ab_to_ah(ab, i);
                        ieee80211_restart_hw(ah->hw);
 
 void ath12k_core_hw_group_unassign(struct ath12k_base *ab)
 {
-       struct ath12k_hw_group *ag = ab->ag;
+       struct ath12k_hw_group *ag = ath12k_ab_to_ag(ab);
        u8 device_id = ab->device_id;
        int num_probed;
 
                ath12k_core_hw_group_free(ag);
 }
 
-static void ath12k_core_device_cleanup(struct ath12k_base *ab)
-{
-       mutex_lock(&ab->core_lock);
-
-       ath12k_hif_irq_disable(ab);
-       ath12k_core_pdev_destroy(ab);
-       ath12k_mac_unregister(ab);
-       ath12k_mac_destroy(ab);
-       ath12k_core_stop(ab);
-
-       mutex_unlock(&ab->core_lock);
-}
-
 static void ath12k_core_hw_group_destroy(struct ath12k_hw_group *ag)
 {
        struct ath12k_base *ab;
 
        mutex_lock(&ag->mutex);
 
+       ath12k_core_hw_group_stop(ag);
+
        for (i = 0; i < ag->num_devices; i++) {
                ab = ag->ab[i];
                if (!ab)
                        continue;
 
-               ath12k_core_device_cleanup(ab);
+               mutex_lock(&ab->core_lock);
+               ath12k_core_stop(ab);
+               mutex_unlock(&ab->core_lock);
        }
 
        mutex_unlock(&ag->mutex);