forked from Minki/linux
Bluetooth: hci_qca: Bug fixes for SSR
1.During SSR for command time out if BT SoC goes to inresponsive state, power cycling of BT SoC was not happening. Given the fix by sending hw error event to reset the BT SoC. 2.If SSR is triggered then ignore the transmit data requests to BT SoC until SSR is completed. Signed-off-by: Venkata Lakshmi Narayana Gubba <gubbaven@codeaurora.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
parent
33bfd94a05
commit
3344537f61
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user