Merge "Bluetooth : Recover BT, if hardware error event is received from the SOC"
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 42c8823..35c57c0 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -1,6 +1,6 @@
 /*
    BlueZ - Bluetooth protocol stack for Linux
-   Copyright (c) 2000-2001, 2010-2012 The Linux Foundation. All rights reserved.
+   Copyright (c) 2000-2001, 2010-2013 The Linux Foundation. All rights reserved.
 
    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
 
@@ -1145,6 +1145,11 @@
 	__le16   opcode;
 } __packed;
 
+#define HCI_EV_HARDWARE_ERROR		0x10
+struct hci_ev_hardware_error {
+	__u8   hw_err_code;
+} __packed;
+
 #define HCI_EV_ROLE_CHANGE		0x12
 struct hci_ev_role_change {
 	__u8     status;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index d243646..2dba071 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2426,6 +2426,21 @@
 	}
 }
 
+static inline void hci_hardware_error_evt(struct hci_dev *hdev,
+					struct sk_buff *skb)
+{
+	struct hci_ev_hardware_error *ev = (void *) skb->data;
+
+	BT_ERR("hdev=%p, hw_err_code = %u", hdev, ev->hw_err_code);
+
+	if (hdev && hdev->dev_type == HCI_BREDR) {
+		hci_dev_lock_bh(hdev);
+		mgmt_powered(hdev->id, 1);
+		hci_dev_unlock_bh(hdev);
+	}
+
+}
+
 static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_ev_role_change *ev = (void *) skb->data;
@@ -3555,6 +3570,10 @@
 		hci_cmd_status_evt(hdev, skb);
 		break;
 
+	case HCI_EV_HARDWARE_ERROR:
+		hci_hardware_error_evt(hdev, skb);
+		break;
+
 	case HCI_EV_ROLE_CHANGE:
 		hci_role_change_evt(hdev, skb);
 		break;