diff options
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r-- | drivers/bluetooth/hci_qca.c | 40 |
1 files changed, 36 insertions, 4 deletions
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 7e395469ca4f..3d1300286993 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -72,7 +72,8 @@ enum qca_flags { QCA_DROP_VENDOR_EVENT, QCA_SUSPENDING, QCA_MEMDUMP_COLLECTION, - QCA_HW_ERROR_EVENT + QCA_HW_ERROR_EVENT, + QCA_SSR_TRIGGERED }; enum qca_capabilities { @@ -854,6 +855,13 @@ static int qca_enqueue(struct hci_uart *hu, struct sk_buff *skb) 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); @@ -1123,6 +1131,7 @@ static int qca_controller_memdump_event(struct hci_dev *hdev, 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); @@ -1481,6 +1490,7 @@ static void qca_hw_error(struct hci_dev *hdev, u8 code) 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); @@ -1529,10 +1539,30 @@ static void qca_cmd_timeout(struct hci_dev *hdev) 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) @@ -1643,6 +1673,8 @@ retry: 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); |