Bladeren bron

btfmcodec: unblock waiting threads during usecase shutdown

This change notifies waiting thread when usecase shutdown
is triggered and also flush work queues.

Change-Id: If523e806dc23fc256e82c4eac30f7aa79b119f55
Balakrishna Godavarthi 2 jaren geleden
bovenliggende
commit
e7e85692a1

+ 20 - 1
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);

+ 7 - 2
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;
 		}

+ 4 - 2
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;
 	}
 

+ 3 - 0
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,