struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev);
        struct hci_uart *hu = &qcadev->serdev_hu;
        struct hci_dev *hdev = hu->hdev;
-       struct qca_data *qca = hu->priv;
        const u8 ibs_wake_cmd[] = { 0xFD };
        const u8 edl_reset_soc_cmd[] = { 0x01, 0x00, 0xFC, 0x01, 0x05 };
 
        if (qcadev->btsoc_type == QCA_QCA6390) {
-               if (test_bit(QCA_BT_OFF, &qca->flags) ||
-                   !test_bit(HCI_RUNNING, &hdev->flags))
+               /* The purpose of sending the VSC is to reset SOC into a initial
+                * state and the state will ensure next hdev->setup() success.
+                * if HCI_QUIRK_NON_PERSISTENT_SETUP is set, it means that
+                * hdev->setup() can do its job regardless of SoC state, so
+                * don't need to send the VSC.
+                * if HCI_SETUP is set, it means that hdev->setup() was never
+                * invoked and the SOC is already in the initial state, so
+                * don't also need to send the VSC.
+                */
+               if (test_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks) ||
+                   hci_dev_test_flag(hdev, HCI_SETUP))
                        return;
 
+               /* The serdev must be in open state when conrol logic arrives
+                * here, so also fix the use-after-free issue caused by that
+                * the serdev is flushed or wrote after it is closed.
+                */
                serdev_device_write_flush(serdev);
                ret = serdev_device_write_buf(serdev, ibs_wake_cmd,
                                              sizeof(ibs_wake_cmd));