struct ishtp_device *ish_dev_init(struct pci_dev *pdev);
 int ish_hw_start(struct ishtp_device *dev);
 void ish_device_disable(struct ishtp_device *dev);
+int ish_disable_dma(struct ishtp_device *dev);
 
 #endif /* _ISHTP_HW_ISH_H_ */
 
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/sched.h>
+#include <linux/suspend.h>
 #include <linux/interrupt.h>
 #include <linux/workqueue.h>
 #define CREATE_TRACE_POINTS
        {}
 };
 
+static inline bool ish_should_enter_d0i3(struct pci_dev *pdev)
+{
+       return !pm_suspend_via_firmware() || pdev->device == CHV_DEVICE_ID;
+}
+
 /**
  * ish_probe() - PCI driver probe callback
  * @pdev:      pci device
        /* mapping IO device memory */
        hw->mem_addr = pcim_iomap_table(pdev)[0];
        ishtp->pdev = pdev;
-       pdev->dev_flags |= PCI_DEV_FLAGS_NO_D3;
 
        /* request and enable interrupt */
        ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
        struct ishtp_device *ishtp_dev = pci_get_drvdata(pdev);
 
        ishtp_bus_remove_all_clients(ishtp_dev, false);
-       pdev->dev_flags &= ~PCI_DEV_FLAGS_NO_D3;
        ish_device_disable(ishtp_dev);
 }
 
        uint32_t fwsts;
        int ret;
 
+       pdev->dev_flags &= ~PCI_DEV_FLAGS_NO_D3;
+
        /* Get ISH FW status */
        fwsts = IPC_GET_ISH_FWSTS(dev->ops->get_fw_status(dev));
 
                                                 !dev->suspend_flag,
                                                  msecs_to_jiffies(25));
 
+       if (ish_should_enter_d0i3(pdev)) {
+               /* Set the NO_D3 flag, the ISH would enter D0i3 */
+               pdev->dev_flags |= PCI_DEV_FLAGS_NO_D3;
+       } else {
+               /*
+                * Clear the DMA bit before putting ISH into D3,
+                * or ISH FW would reset automatically.
+                */
+               ish_disable_dma(dev);
+       }
+
        return 0;
 }