diff --git a/btfmcodec/btfm_codec.c b/btfmcodec/btfm_codec.c index 75da3097ca..6b62f91936 100644 --- a/btfmcodec/btfm_codec.c +++ b/btfmcodec/btfm_codec.c @@ -94,6 +94,7 @@ static int btfmcodec_dev_release(struct inode *inode, struct file *file) { struct btfmcodec_char_device *btfmcodec_dev = cdev_to_btfmchardev(inode->i_cdev); unsigned long flags; + int idx; BTFMCODEC_INFO("for %s by %s:%d active_clients[%u]\n", btfmcodec_dev->dev_name, current->comm, @@ -110,6 +111,16 @@ static int btfmcodec_dev_release(struct inode *inode, struct file *file) skb_queue_purge(&btfmcodec_dev->rxq); } + /* Notify waiting clients that client is closed or killed */ + for (idx = 0; idx < BTM_PKT_TYPE_MAX; idx++) { + btfmcodec_dev->status[idx] = BTM_RSP_NOT_RECV_CLIENT_KILLED; + wake_up_interruptible(&btfmcodec_dev->rsp_wait_q[idx]); + } + + cancel_work_sync(&btfmcodec_dev->wq_hwep_shutdown); + cancel_work_sync(&btfmcodec_dev->wq_hwep_configure); + cancel_work_sync(&btfmcodec_dev->wq_prepare_bearer); + btfmcodec->states.current_state = IDLE; btfmcodec->states.next_state = IDLE; return 0; @@ -140,8 +151,16 @@ static void btfmcodec_dev_rxwork(struct work_struct *work) idx = BTM_PKT_TYPE_PREPARE_REQ; BTFMCODEC_DBG("BTM_BTFMCODEC_PREPARE_AUDIO_BEARER_SWITCH_REQ"); if (len == BTM_PREPARE_AUDIO_BEARER_SWITCH_REQ_LEN) { + /* there are chances where bearer indication is not recevied, + * So inform waiting thread to unblock itself and move to + * previous state. + */ + if (btfmcodec_dev->status[BTM_PKT_TYPE_BEARER_SWITCH_IND] == BTM_WAITING_RSP) { + BTFMCODEC_DBG("Notifying waiting beare indications"); + btfmcodec_dev->status[BTM_PKT_TYPE_BEARER_SWITCH_IND] = BTM_FAIL_RESP_RECV; + wake_up_interruptible(&btfmcodec_dev->rsp_wait_q[BTM_PKT_TYPE_BEARER_SWITCH_IND]); + } btfmcodec_dev->status[idx] = skb->data[0]; - BTFMCODEC_INFO("prepare wq_prepare_bearer:%p", btfmcodec_dev->wq_prepare_bearer); queue_work(btfmcodec_dev->workqueue, &btfmcodec_dev->wq_prepare_bearer); } else { BTFMCODEC_ERR("wrong packet format with len:%d", len); diff --git a/btfmcodec/btfm_codec_btadv_interface.c b/btfmcodec/btfm_codec_btadv_interface.c index 79f0488df6..b85bcaa362 100644 --- a/btfmcodec/btfm_codec_btadv_interface.c +++ b/btfmcodec/btfm_codec_btadv_interface.c @@ -30,7 +30,8 @@ void btfmcodec_initiate_hwep_shutdown(struct btfmcodec_char_device *btfmcodec_de if (*status == BTM_RSP_RECV) { BTFMCODEC_ERR("sucessfully closed hwep"); return; - } else if (*status == BTM_FAIL_RESP_RECV) { + } else if (*status == BTM_FAIL_RESP_RECV || + *status == BTM_RSP_NOT_RECV_CLIENT_KILLED) { BTFMCODEC_ERR("Failed to close hwep"); return; } @@ -136,6 +137,9 @@ int btfmcodec_wait_for_bearer_ind(struct btfmcodec_char_device *btfmcodec_dev) } else if (*status == BTM_FAIL_RESP_RECV) { BTFMCODEC_ERR("Rx BTM_BEARER_SWITCH_IND with failure status"); ret = -1; + } else if (*status == BTM_RSP_NOT_RECV_CLIENT_KILLED) { + BTFMCODEC_ERR("client killed so moving further"); + ret = -1; } } @@ -162,7 +166,8 @@ int btfmcodec_initiate_hwep_configuration(struct btfmcodec_char_device *btfmcode } else { if (*status == BTM_RSP_RECV) { ret = 0; - } else if (*status == BTM_FAIL_RESP_RECV) { + } else if (*status == BTM_FAIL_RESP_RECV || + *status == BTM_RSP_NOT_RECV_CLIENT_KILLED) { BTFMCODEC_ERR("Failed to close hwep moving back to previous state"); ret = -1; } diff --git a/btfmcodec/btfm_codec_interface.c b/btfmcodec/btfm_codec_interface.c index be360f34a9..6672cd8e70 100644 --- a/btfmcodec/btfm_codec_interface.c +++ b/btfmcodec/btfm_codec_interface.c @@ -255,7 +255,8 @@ int btfmcodec_hwep_shutdown(struct btfmcodec_data *btfmcodec, int id) } else { if (*status == BTM_RSP_RECV) ret = 0; - else if (*status == BTM_FAIL_RESP_RECV) + else if (*status == BTM_FAIL_RESP_RECV || + *status == BTM_RSP_NOT_RECV_CLIENT_KILLED) ret = -1; } } else { @@ -489,7 +490,8 @@ static int btfmcodec_configure_master(struct btfmcodec_data *btfmcodec, uint8_t } else { if (*status == BTM_RSP_RECV) return 0; - else if (*status == BTM_FAIL_RESP_RECV) + else if (*status == BTM_FAIL_RESP_RECV || + *status == BTM_RSP_NOT_RECV_CLIENT_KILLED) return -1; } diff --git a/btfmcodec/include/btfm_codec_pkt.h b/btfmcodec/include/btfm_codec_pkt.h index 3084b88de5..3e48b7c839 100644 --- a/btfmcodec/include/btfm_codec_pkt.h +++ b/btfmcodec/include/btfm_codec_pkt.h @@ -57,7 +57,10 @@ enum rx_status { BTM_RSP_RECV, /* Response recevied with failure status*/ BTM_FAIL_RESP_RECV, + /* Response not recevied, but client killed */ + BTM_RSP_NOT_RECV_CLIENT_KILLED, }; + enum btfm_kp_status { /* KP processed message succesfully */ MSG_SUCCESS = 0,