QCA_DROP_VENDOR_EVENT,
        QCA_SUSPENDING,
        QCA_MEMDUMP_COLLECTION,
-       QCA_HW_ERROR_EVENT
+       QCA_HW_ERROR_EVENT,
+       QCA_SSR_TRIGGERED
 };
 
 enum qca_capabilities {
        BT_DBG("hu %p qca enq skb %p tx_ibs_state %d", hu, skb,
               qca->tx_ibs_state);
 
+       if (test_bit(QCA_SSR_TRIGGERED, &qca->flags)) {
+               /* As SSR is in progress, ignore the packets */
+               bt_dev_dbg(hu->hdev, "SSR is in progress");
+               kfree_skb(skb);
+               return 0;
+       }
+
        /* Prepend skb with frame type */
        memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
 
        struct hci_uart *hu = hci_get_drvdata(hdev);
        struct qca_data *qca = hu->priv;
 
+       set_bit(QCA_SSR_TRIGGERED, &qca->flags);
        skb_queue_tail(&qca->rx_memdump_q, skb);
        queue_work(qca->workqueue, &qca->ctrl_memdump_evt);
 
        struct hci_uart *hu = hci_get_drvdata(hdev);
        struct qca_data *qca = hu->priv;
 
+       set_bit(QCA_SSR_TRIGGERED, &qca->flags);
        set_bit(QCA_HW_ERROR_EVENT, &qca->flags);
        bt_dev_info(hdev, "mem_dump_status: %d", qca->memdump_state);
 
        struct hci_uart *hu = hci_get_drvdata(hdev);
        struct qca_data *qca = hu->priv;
 
-       if (qca->memdump_state == QCA_MEMDUMP_IDLE)
+       set_bit(QCA_SSR_TRIGGERED, &qca->flags);
+       if (qca->memdump_state == QCA_MEMDUMP_IDLE) {
+               set_bit(QCA_MEMDUMP_COLLECTION, &qca->flags);
                qca_send_crashbuffer(hu);
-       else
-               bt_dev_info(hdev, "Dump collection is in process");
+               qca_wait_for_dump_collection(hdev);
+       } else if (qca->memdump_state == QCA_MEMDUMP_COLLECTING) {
+               /* Let us wait here until memory dump collected or
+                * memory dump timer expired.
+                */
+               bt_dev_info(hdev, "waiting for dump to complete");
+               qca_wait_for_dump_collection(hdev);
+       }
+
+       mutex_lock(&qca->hci_memdump_lock);
+       if (qca->memdump_state != QCA_MEMDUMP_COLLECTED) {
+               qca->memdump_state = QCA_MEMDUMP_TIMEOUT;
+               if (!test_bit(QCA_HW_ERROR_EVENT, &qca->flags)) {
+                       /* Inject hw error event to reset the device
+                        * and driver.
+                        */
+                       hci_reset_dev(hu->hdev);
+               }
+       }
+       mutex_unlock(&qca->hci_memdump_lock);
 }
 
 static int qca_wcn3990_init(struct hci_uart *hu)
        if (ret)
                return ret;
 
+       clear_bit(QCA_SSR_TRIGGERED, &qca->flags);
+
        if (qca_is_wcn399x(soc_type)) {
                set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);