msleep(10);
 }
 
-static int ath10k_pci_warm_reset(struct ath10k *ar)
+static void ath10k_pci_warm_reset_cpu(struct ath10k *ar)
 {
        u32 val;
 
-       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset\n");
-
-       spin_lock_bh(&ar->data_lock);
-
-       ar->stats.fw_warm_reset_counter++;
-
-       spin_unlock_bh(&ar->data_lock);
-
-       /* debug */
-       val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
-                               PCIE_INTR_CAUSE_ADDRESS);
-       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot host cpu intr cause: 0x%08x\n",
-                  val);
-
-       val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
-                               CPU_INTR_ADDRESS);
-       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot target cpu intr cause: 0x%08x\n",
-                  val);
-
-       /* disable pending irqs */
-       ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS +
-                          PCIE_INTR_ENABLE_ADDRESS, 0);
-
-       ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS +
-                          PCIE_INTR_CLR_ADDRESS, ~0);
-
-       msleep(100);
-
-       /* clear fw indicator */
        ath10k_pci_write32(ar, FW_INDICATOR_ADDRESS, 0);
 
-       /* clear target LF timer interrupts */
        val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
-                               SOC_LF_TIMER_CONTROL0_ADDRESS);
-       ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS +
-                          SOC_LF_TIMER_CONTROL0_ADDRESS,
-                          val & ~SOC_LF_TIMER_CONTROL0_ENABLE_MASK);
+                               SOC_RESET_CONTROL_ADDRESS);
+       ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
+                          val | SOC_RESET_CONTROL_CPU_WARM_RST_MASK);
+}
+
+static void ath10k_pci_warm_reset_ce(struct ath10k *ar)
+{
+       u32 val;
 
-       /* reset CE */
        val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
                                SOC_RESET_CONTROL_ADDRESS);
+
        ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
                           val | SOC_RESET_CONTROL_CE_RST_MASK);
-       val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
-                               SOC_RESET_CONTROL_ADDRESS);
        msleep(10);
-
-       /* unreset CE */
        ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
                           val & ~SOC_RESET_CONTROL_CE_RST_MASK);
+}
+
+static void ath10k_pci_warm_reset_clear_lf(struct ath10k *ar)
+{
+       u32 val;
+
        val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
-                               SOC_RESET_CONTROL_ADDRESS);
-       msleep(10);
+                               SOC_LF_TIMER_CONTROL0_ADDRESS);
+       ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS +
+                          SOC_LF_TIMER_CONTROL0_ADDRESS,
+                          val & ~SOC_LF_TIMER_CONTROL0_ENABLE_MASK);
+}
 
-       ath10k_pci_warm_reset_si0(ar);
+static int ath10k_pci_warm_reset(struct ath10k *ar)
+{
+       int ret;
+
+       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset\n");
 
-       /* debug */
-       val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
-                               PCIE_INTR_CAUSE_ADDRESS);
-       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot host cpu intr cause: 0x%08x\n",
-                  val);
+       spin_lock_bh(&ar->data_lock);
+       ar->stats.fw_warm_reset_counter++;
+       spin_unlock_bh(&ar->data_lock);
 
-       val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
-                               CPU_INTR_ADDRESS);
-       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot target cpu intr cause: 0x%08x\n",
-                  val);
+       ath10k_pci_irq_disable(ar);
 
-       /* CPU warm reset */
-       val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
-                               SOC_RESET_CONTROL_ADDRESS);
-       ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
-                          val | SOC_RESET_CONTROL_CPU_WARM_RST_MASK);
+       /* Make sure the target CPU is not doing anything dangerous, e.g. if it
+        * were to access copy engine while host performs copy engine reset
+        * then it is possible for the device to confuse pci-e controller to
+        * the point of bringing host system to a complete stop (i.e. hang).
+        */
+       ath10k_pci_warm_reset_si0(ar);
+       ath10k_pci_warm_reset_cpu(ar);
+       ath10k_pci_init_pipes(ar);
+       ath10k_pci_wait_for_target_init(ar);
 
-       val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
-                               SOC_RESET_CONTROL_ADDRESS);
-       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot target reset state: 0x%08x\n",
-                  val);
+       ath10k_pci_warm_reset_clear_lf(ar);
+       ath10k_pci_warm_reset_ce(ar);
+       ath10k_pci_warm_reset_cpu(ar);
+       ath10k_pci_init_pipes(ar);
 
-       msleep(100);
+       ret = ath10k_pci_wait_for_target_init(ar);
+       if (ret) {
+               ath10k_warn(ar, "failed to wait for target init: %d\n", ret);
+               return ret;
+       }
 
        ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset complete\n");