Merge "bluetooth: Reset BT stack when wcnss chip resets" into msm-3.0
diff --git a/drivers/bluetooth/hci_smd.c b/drivers/bluetooth/hci_smd.c
index dbd1bd4..332922e 100644
--- a/drivers/bluetooth/hci_smd.c
+++ b/drivers/bluetooth/hci_smd.c
@@ -25,6 +25,7 @@
#include <linux/string.h>
#include <linux/skbuff.h>
#include <linux/wakelock.h>
+#include <linux/workqueue.h>
#include <linux/uaccess.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -47,6 +48,7 @@
static int hcismd_set_enable(const char *val, struct kernel_param *kp);
module_param_call(hcismd_set, hcismd_set_enable, NULL, &hcismd_set, 0644);
+static void hci_dev_restart(struct work_struct *worker);
struct hci_smd_data {
struct hci_dev *hdev;
@@ -312,6 +314,7 @@
{
struct hci_dev *hdev = hs.hdev;
struct hci_smd_data *hsmd = &hs;
+ struct work_struct *reset_worker;
int len = 0;
if (!hdev) {
@@ -335,6 +338,13 @@
case SMD_EVENT_CLOSE:
BT_INFO("Closing HCI-SMD channel :%s", EVENT_CHANNEL);
hci_smd_close(hdev);
+ reset_worker = kzalloc(sizeof(*reset_worker), GFP_ATOMIC);
+ if (!reset_worker) {
+ BT_ERR("Out of memory");
+ break;
+ }
+ INIT_WORK(reset_worker, hci_dev_restart);
+ schedule_work(reset_worker);
break;
default:
break;
@@ -464,6 +474,15 @@
}
}
+static void hci_dev_restart(struct work_struct *worker)
+{
+ mutex_lock(&hci_smd_enable);
+ hci_smd_deregister_dev(&hs);
+ hci_smd_register_dev(&hs);
+ mutex_unlock(&hci_smd_enable);
+ kfree(worker);
+}
+
static int hcismd_set_enable(const char *val, struct kernel_param *kp)
{
int ret = 0;