fm_hci: check hci status before enqueue evt
new event after HCI_EV_CMD_COMPLETE may cause
deal lock issue and tyr to check hci status before
enqueue event
CRs-fixed: 3152512
Change-Id: I982a726af7ca9e76bf6922e38211a5f36f223c79
diff --git a/fm_hci/fm_hci.cpp b/fm_hci/fm_hci.cpp
index 8bad980..f33275e 100644
--- a/fm_hci/fm_hci.cpp
+++ b/fm_hci/fm_hci.cpp
@@ -124,12 +124,37 @@
{
ALOGV("%s: putting lock before enqueue ", __func__);
- hci.rx_cond_mtx.lock();
+ /*
+ * enqueue_fm_rx_event may need to wait for rx_cond_mtx here as
+ * last event is still under processing, besides current event
+ * has held internal_mutex_ when OnPacketReady called in data_handler.cpp
+ * if last event is HCI_EV_CMD_COMPLETE, it will try to hold
+ * internal_mutex_ again when calling close in data_handler,
+ * thus, last event will wait for internal_mutex_ while new event
+ * will wait util last event done, finally dead lock occurs.
+ * so we try to check hci state here if rx_cond_mtx is still locked
+ */
+ int tryLockCount = 0;
+ while (1) {
+ if (!hci.rx_cond_mtx.try_lock()) {
+ if (hci.state == FM_RADIO_DISABLING || hci.state == FM_RADIO_DISABLED) {
+ ALOGI("%s: can't lock rx_cond_mtx and hci is not available", __func__);
+ return FM_HC_STATUS_NULL_POINTER;
+ }
+ usleep(1000);
+ tryLockCount++;
+ continue;
+ } else {
+ break;
+ }
+ }
+ hci.rx_queue_mtx.lock();
hci.rx_event_queue.push(hdr);
- hci.rx_cond_mtx.unlock();
+ hci.rx_queue_mtx.unlock();
ALOGV("%s:notify to waiting thred", __func__);
hci.rx_cond.notify_all();
- ALOGI("%s: FM-Event ENQUEUED SUCCESSFULLY", __func__);
+ ALOGI("%s: FM-Event ENQUEUED SUCCESSFULLY tryLockCount = %d", __func__, tryLockCount);
+ hci.rx_cond_mtx.unlock();
return FM_HC_STATUS_SUCCESS;
}
@@ -153,14 +178,17 @@
ALOGI("%s", __func__);
while (1) {
+ hci.rx_queue_mtx.lock();
if (hci.rx_event_queue.empty()) {
ALOGI("No more FM Events are available in the RX Queue");
+ hci.rx_queue_mtx.unlock();
return;
} else {
}
evt_buf = hci.rx_event_queue.front();
hci.rx_event_queue.pop();
+ hci.rx_queue_mtx.unlock();
if (evt_buf->evt_code == FM_CMD_COMPLETE) {
ALOGI("%s: FM_CMD_COMPLETE: current_credits %d, %d Credits got from the SOC", __func__, hci.command_credits, evt_buf->params[0]);
@@ -546,6 +574,7 @@
memcpy(temp, event.data(), event.size());
ALOGI("%s: evt_code: 0x%x", __func__, temp->evt_code);
enqueue_fm_rx_event(temp);
+ ALOGI("%s: evt_code: 0x%x done", __func__, temp->evt_code);
} else {
ALOGE("%s: Memory Allocation failed for event buffer ",__func__);
}
diff --git a/fm_hci/fm_hci.h b/fm_hci/fm_hci.h
index aa3c2b7..f209aaa 100644
--- a/fm_hci/fm_hci.h
+++ b/fm_hci/fm_hci.h
@@ -53,6 +53,8 @@
std::mutex tx_queue_mtx;
+ std::mutex rx_queue_mtx;
+
std::condition_variable cmd_credits_cond;
std::queue<struct fm_command_header_t *> tx_cmd_queue;