bluetooth:Clean up in hci device registration while Bt turn off

Change-Id: I46fe1bfcd53b6a1a405426f69cec75b20590ade6
CRs-fixed: 311458
Signed-off-by: Bhasker Neti <bneti@codeaurora.org>
diff --git a/drivers/bluetooth/hci_smd.c b/drivers/bluetooth/hci_smd.c
index a321849..3c4aa8f 100644
--- a/drivers/bluetooth/hci_smd.c
+++ b/drivers/bluetooth/hci_smd.c
@@ -36,8 +36,6 @@
 #define RX_Q_MONITOR		(1)	/* 1 milli second */
 
 
-static unsigned int driver_state;
-
 static int hcismd_set;
 static DEFINE_MUTEX(hci_smd_enable);
 
@@ -127,7 +125,8 @@
 
 static void hci_smd_destruct(struct hci_dev *hdev)
 {
-	kfree(hdev->driver_data);
+	if (NULL != hdev->driver_data)
+		kfree(hdev->driver_data);
 }
 
 static void hci_smd_recv_data(unsigned long arg)
@@ -388,33 +387,25 @@
 	int rc;
 
 	/* Initialize and register HCI device */
-	if (!driver_state) {
-		hdev = hci_alloc_dev();
-		if (!hdev) {
-			BT_ERR("Can't allocate HCI device");
-			return -ENOMEM;
-		}
-
-		hsmd->hdev = hdev;
-		hdev->bus = HCI_SMD;
-		hdev->driver_data = hsmd;
-		hdev->open  = hci_smd_open;
-		hdev->close = hci_smd_close;
-		hdev->send  = hci_smd_send_frame;
-		hdev->destruct = hci_smd_destruct;
-		hdev->owner = THIS_MODULE;
+	hdev = hci_alloc_dev();
+	if (!hdev) {
+		BT_ERR("Can't allocate HCI device");
+		return -ENOMEM;
 	}
 
+	hsmd->hdev = hdev;
+	hdev->bus = HCI_SMD;
+	hdev->driver_data = NULL;
+	hdev->open  = hci_smd_open;
+	hdev->close = hci_smd_close;
+	hdev->send  = hci_smd_send_frame;
+	hdev->destruct = hci_smd_destruct;
+	hdev->owner = THIS_MODULE;
+
 	tasklet_init(&hsmd->hci_event_task,
 			hci_smd_recv_event, (unsigned long) hsmd);
 	tasklet_init(&hsmd->hci_data_task,
 			hci_smd_recv_data, (unsigned long) hsmd);
-	if (!driver_state) {
-		wake_lock_init(&hs.wake_lock_rx, WAKE_LOCK_SUSPEND,
-				 "msm_smd_Rx");
-		wake_lock_init(&hs.wake_lock_tx, WAKE_LOCK_SUSPEND,
-				 "msm_smd_Tx");
-	}
 	/*
 	 * Setup the timer to monitor whether the Rx queue is empty,
 	 * to control the wake lock release
@@ -442,29 +433,32 @@
 	/* Disable the read interrupts on the channel */
 	smd_disable_read_intr(hsmd->event_channel);
 	smd_disable_read_intr(hsmd->data_channel);
-	if (!driver_state) {
-		if (hci_register_dev(hdev) < 0) {
-			BT_ERR("Can't register HCI device");
-			hci_free_dev(hdev);
-			return -ENODEV;
-		}
-		driver_state = 1;
+	if (hci_register_dev(hdev) < 0) {
+		BT_ERR("Can't register HCI device");
+		hci_free_dev(hdev);
+		return -ENODEV;
 	}
 	return 0;
 }
 
-static void hci_smd_deregister_dev(void)
+static void hci_smd_deregister_dev(struct hci_smd_data *hsmd)
 {
 	smd_close(hs.event_channel);
 	smd_close(hs.data_channel);
 
 	if (wake_lock_active(&hs.wake_lock_rx))
 		wake_unlock(&hs.wake_lock_rx);
+	if (wake_lock_active(&hs.wake_lock_tx))
+		wake_unlock(&hs.wake_lock_tx);
 
 	/*Destroy the timer used to monitor the Rx queue for emptiness */
 	del_timer_sync(&hs.rx_q_timer);
 	tasklet_kill(&hs.hci_event_task);
 	tasklet_kill(&hs.hci_data_task);
+	if (hci_unregister_dev(hsmd->hdev) < 0)
+		BT_ERR("Can't unregister HCI device %s", hsmd->hdev->name);
+
+	hci_free_dev(hsmd->hdev);
 }
 
 static int hcismd_set_enable(const char *val, struct kernel_param *kp)
@@ -484,7 +478,7 @@
 		hci_smd_register_dev(&hs);
 	break;
 	case 0:
-		hci_smd_deregister_dev();
+		hci_smd_deregister_dev(&hs);
 	break;
 	default:
 		ret = -EFAULT;
@@ -494,7 +488,22 @@
 	mutex_unlock(&hci_smd_enable);
 	return ret;
 }
+static int  __init hci_smd_init(void)
+{
+	wake_lock_init(&hs.wake_lock_rx, WAKE_LOCK_SUSPEND,
+			 "msm_smd_Rx");
+	wake_lock_init(&hs.wake_lock_tx, WAKE_LOCK_SUSPEND,
+			 "msm_smd_Tx");
+	return 0;
+}
+module_init(hci_smd_init);
 
+static void __exit hci_smd_exit(void)
+{
+	wake_lock_destroy(&hs.wake_lock_rx);
+	wake_lock_destroy(&hs.wake_lock_tx);
+}
+module_exit(hci_smd_exit);
 
 MODULE_AUTHOR("Ankur Nandwani <ankurn@codeaurora.org>");
 MODULE_DESCRIPTION("Bluetooth SMD driver");