Commit 3344537f authored by Venkata Lakshmi Narayana Gubba's avatar Venkata Lakshmi Narayana Gubba Committed by Marcel Holtmann

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: default avatarVenkata Lakshmi Narayana Gubba <gubbaven@codeaurora.org>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 33bfd94a
...@@ -72,7 +72,8 @@ enum qca_flags { ...@@ -72,7 +72,8 @@ enum qca_flags {
QCA_DROP_VENDOR_EVENT, QCA_DROP_VENDOR_EVENT,
QCA_SUSPENDING, QCA_SUSPENDING,
QCA_MEMDUMP_COLLECTION, QCA_MEMDUMP_COLLECTION,
QCA_HW_ERROR_EVENT QCA_HW_ERROR_EVENT,
QCA_SSR_TRIGGERED
}; };
enum qca_capabilities { enum qca_capabilities {
...@@ -854,6 +855,13 @@ static int qca_enqueue(struct hci_uart *hu, struct sk_buff *skb) ...@@ -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, BT_DBG("hu %p qca enq skb %p tx_ibs_state %d", hu, skb,
qca->tx_ibs_state); 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 */ /* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1); 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, ...@@ -1123,6 +1131,7 @@ static int qca_controller_memdump_event(struct hci_dev *hdev,
struct hci_uart *hu = hci_get_drvdata(hdev); struct hci_uart *hu = hci_get_drvdata(hdev);
struct qca_data *qca = hu->priv; struct qca_data *qca = hu->priv;
set_bit(QCA_SSR_TRIGGERED, &qca->flags);
skb_queue_tail(&qca->rx_memdump_q, skb); skb_queue_tail(&qca->rx_memdump_q, skb);
queue_work(qca->workqueue, &qca->ctrl_memdump_evt); queue_work(qca->workqueue, &qca->ctrl_memdump_evt);
...@@ -1481,6 +1490,7 @@ static void qca_hw_error(struct hci_dev *hdev, u8 code) ...@@ -1481,6 +1490,7 @@ static void qca_hw_error(struct hci_dev *hdev, u8 code)
struct hci_uart *hu = hci_get_drvdata(hdev); struct hci_uart *hu = hci_get_drvdata(hdev);
struct qca_data *qca = hu->priv; struct qca_data *qca = hu->priv;
set_bit(QCA_SSR_TRIGGERED, &qca->flags);
set_bit(QCA_HW_ERROR_EVENT, &qca->flags); set_bit(QCA_HW_ERROR_EVENT, &qca->flags);
bt_dev_info(hdev, "mem_dump_status: %d", qca->memdump_state); bt_dev_info(hdev, "mem_dump_status: %d", qca->memdump_state);
...@@ -1529,10 +1539,30 @@ static void qca_cmd_timeout(struct hci_dev *hdev) ...@@ -1529,10 +1539,30 @@ static void qca_cmd_timeout(struct hci_dev *hdev)
struct hci_uart *hu = hci_get_drvdata(hdev); struct hci_uart *hu = hci_get_drvdata(hdev);
struct qca_data *qca = hu->priv; 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); qca_send_crashbuffer(hu);
else qca_wait_for_dump_collection(hdev);
bt_dev_info(hdev, "Dump collection is in process"); } 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) static int qca_wcn3990_init(struct hci_uart *hu)
...@@ -1643,6 +1673,8 @@ static int qca_setup(struct hci_uart *hu) ...@@ -1643,6 +1673,8 @@ static int qca_setup(struct hci_uart *hu)
if (ret) if (ret)
return ret; return ret;
clear_bit(QCA_SSR_TRIGGERED, &qca->flags);
if (qca_is_wcn399x(soc_type)) { if (qca_is_wcn399x(soc_type)) {
set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment