Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluetooth-next-2.6
diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c
old mode 100755
new mode 100644
index 5ab258b..6a160c1
--- a/drivers/bluetooth/hci_ath.c
+++ b/drivers/bluetooth/hci_ath.c
@@ -163,7 +163,7 @@
 	struct ath_struct *ath = hu->priv;
 
 	if (bt_cb(skb)->pkt_type == HCI_SCODATA_PKT) {
-		kfree(skb);
+		kfree_skb(skb);
 		return 0;
 	}
 
@@ -217,7 +217,7 @@
 	.flush = ath_flush,
 };
 
-int ath_init(void)
+int __init ath_init(void)
 {
 	int err = hci_uart_register_proto(&athp);
 
@@ -229,7 +229,7 @@
 	return err;
 }
 
-int ath_deinit(void)
+int __exit ath_deinit(void)
 {
 	return hci_uart_unregister_proto(&athp);
 }
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c
index 42d69d4..9c5b2dc 100644
--- a/drivers/bluetooth/hci_bcsp.c
+++ b/drivers/bluetooth/hci_bcsp.c
@@ -739,7 +739,7 @@
 	.flush		= bcsp_flush
 };
 
-int bcsp_init(void)
+int __init bcsp_init(void)
 {
 	int err = hci_uart_register_proto(&bcsp);
 
@@ -751,7 +751,7 @@
 	return err;
 }
 
-int bcsp_deinit(void)
+int __exit bcsp_deinit(void)
 {
 	return hci_uart_unregister_proto(&bcsp);
 }
diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c
index 3f038f5..7b8ad93 100644
--- a/drivers/bluetooth/hci_h4.c
+++ b/drivers/bluetooth/hci_h4.c
@@ -151,107 +151,8 @@
 /* Recv data */
 static int h4_recv(struct hci_uart *hu, void *data, int count)
 {
-	struct h4_struct *h4 = hu->priv;
-	register char *ptr;
-	struct hci_event_hdr *eh;
-	struct hci_acl_hdr   *ah;
-	struct hci_sco_hdr   *sh;
-	register int len, type, dlen;
-
-	BT_DBG("hu %p count %d rx_state %ld rx_count %ld", 
-			hu, count, h4->rx_state, h4->rx_count);
-
-	ptr = data;
-	while (count) {
-		if (h4->rx_count) {
-			len = min_t(unsigned int, h4->rx_count, count);
-			memcpy(skb_put(h4->rx_skb, len), ptr, len);
-			h4->rx_count -= len; count -= len; ptr += len;
-
-			if (h4->rx_count)
-				continue;
-
-			switch (h4->rx_state) {
-			case H4_W4_DATA:
-				BT_DBG("Complete data");
-
-				hci_recv_frame(h4->rx_skb);
-
-				h4->rx_state = H4_W4_PACKET_TYPE;
-				h4->rx_skb = NULL;
-				continue;
-
-			case H4_W4_EVENT_HDR:
-				eh = hci_event_hdr(h4->rx_skb);
-
-				BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen);
-
-				h4_check_data_len(h4, eh->plen);
-				continue;
-
-			case H4_W4_ACL_HDR:
-				ah = hci_acl_hdr(h4->rx_skb);
-				dlen = __le16_to_cpu(ah->dlen);
-
-				BT_DBG("ACL header: dlen %d", dlen);
-
-				h4_check_data_len(h4, dlen);
-				continue;
-
-			case H4_W4_SCO_HDR:
-				sh = hci_sco_hdr(h4->rx_skb);
-
-				BT_DBG("SCO header: dlen %d", sh->dlen);
-
-				h4_check_data_len(h4, sh->dlen);
-				continue;
-			}
-		}
-
-		/* H4_W4_PACKET_TYPE */
-		switch (*ptr) {
-		case HCI_EVENT_PKT:
-			BT_DBG("Event packet");
-			h4->rx_state = H4_W4_EVENT_HDR;
-			h4->rx_count = HCI_EVENT_HDR_SIZE;
-			type = HCI_EVENT_PKT;
-			break;
-
-		case HCI_ACLDATA_PKT:
-			BT_DBG("ACL packet");
-			h4->rx_state = H4_W4_ACL_HDR;
-			h4->rx_count = HCI_ACL_HDR_SIZE;
-			type = HCI_ACLDATA_PKT;
-			break;
-
-		case HCI_SCODATA_PKT:
-			BT_DBG("SCO packet");
-			h4->rx_state = H4_W4_SCO_HDR;
-			h4->rx_count = HCI_SCO_HDR_SIZE;
-			type = HCI_SCODATA_PKT;
-			break;
-
-		default:
-			BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr);
-			hu->hdev->stat.err_rx++;
-			ptr++; count--;
-			continue;
-		};
-
-		ptr++; count--;
-
-		/* Allocate packet */
-		h4->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
-		if (!h4->rx_skb) {
-			BT_ERR("Can't allocate mem for new packet");
-			h4->rx_state = H4_W4_PACKET_TYPE;
-			h4->rx_count = 0;
-			return -ENOMEM;
-		}
-
-		h4->rx_skb->dev = (void *) hu->hdev;
-		bt_cb(h4->rx_skb)->pkt_type = type;
-	}
+	if (hci_recv_stream_fragment(hu->hdev, data, count) < 0)
+		BT_ERR("Frame Reassembly Failed");
 
 	return count;
 }
@@ -272,7 +173,7 @@
 	.flush		= h4_flush,
 };
 
-int h4_init(void)
+int __init h4_init(void)
 {
 	int err = hci_uart_register_proto(&h4p);
 
@@ -284,7 +185,7 @@
 	return err;
 }
 
-int h4_deinit(void)
+int __exit h4_deinit(void)
 {
 	return hci_uart_unregister_proto(&h4p);
 }
diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c
index 5744aba..38595e7 100644
--- a/drivers/bluetooth/hci_ll.c
+++ b/drivers/bluetooth/hci_ll.c
@@ -517,7 +517,7 @@
 	.flush		= ll_flush,
 };
 
-int ll_init(void)
+int __init ll_init(void)
 {
 	int err = hci_uart_register_proto(&llp);
 
@@ -529,7 +529,7 @@
 	return err;
 }
 
-int ll_deinit(void)
+int __exit ll_deinit(void)
 {
 	return hci_uart_unregister_proto(&llp);
 }
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 350b3e6..8b28962 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -256,6 +256,7 @@
 	HCI_CONN_ENCRYPT_PEND,
 	HCI_CONN_RSWITCH_PEND,
 	HCI_CONN_MODE_CHANGE_PEND,
+	HCI_CONN_SCO_SETUP_PEND,
 };
 
 static inline void hci_conn_hash_init(struct hci_dev *hdev)
@@ -336,6 +337,7 @@
 void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
 void hci_add_sco(struct hci_conn *conn, __u16 handle);
 void hci_setup_sync(struct hci_conn *conn, __u16 handle);
+void hci_sco_setup(struct hci_conn *conn, __u8 status);
 
 struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst);
 int hci_conn_del(struct hci_conn *conn);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index e9fef834..0b1e460 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -155,6 +155,27 @@
 	hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
 }
 
+/* Device _must_ be locked */
+void hci_sco_setup(struct hci_conn *conn, __u8 status)
+{
+	struct hci_conn *sco = conn->link;
+
+	BT_DBG("%p", conn);
+
+	if (!sco)
+		return;
+
+	if (!status) {
+		if (lmp_esco_capable(conn->hdev))
+			hci_setup_sync(sco, conn->handle);
+		else
+			hci_add_sco(sco, conn->handle);
+	} else {
+		hci_proto_connect_cfm(sco, status);
+		hci_conn_del(sco);
+	}
+}
+
 static void hci_conn_timeout(unsigned long arg)
 {
 	struct hci_conn *conn = (void *) arg;
@@ -385,10 +406,13 @@
 		acl->power_save = 1;
 		hci_conn_enter_active_mode(acl);
 
-		if (lmp_esco_capable(hdev))
-			hci_setup_sync(sco, acl->handle);
-		else
-			hci_add_sco(sco, acl->handle);
+		if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->pend)) {
+			/* defer SCO setup until mode change completed */
+			set_bit(HCI_CONN_SCO_SETUP_PEND, &acl->pend);
+			return sco;
+		}
+
+		hci_sco_setup(acl, 0x00);
 	}
 
 	return sco;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 995c9f9..8303f1c 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1149,7 +1149,7 @@
 	if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT)
 		return -EILSEQ;
 
-	do {
+	while (count) {
 		rem = hci_reassembly(hdev, type, data, count,
 						type - 1, GFP_ATOMIC);
 		if (rem < 0)
@@ -1157,7 +1157,7 @@
 
 		data += (count - rem);
 		count = rem;
-	} while (count);
+	};
 
 	return rem;
 }
@@ -1170,7 +1170,7 @@
 	int type;
 	int rem = 0;
 
-	do {
+	while (count) {
 		struct sk_buff *skb = hdev->reassembly[STREAM_REASSEMBLY];
 
 		if (!skb) {
@@ -1192,7 +1192,7 @@
 
 		data += (count - rem);
 		count = rem;
-	} while (count);
+	};
 
 	return rem;
 }
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 2069c3b..bfef5ba 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -785,9 +785,13 @@
 	hci_dev_lock(hdev);
 
 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
-	if (conn)
+	if (conn) {
 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
 
+		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
+			hci_sco_setup(conn, status);
+	}
+
 	hci_dev_unlock(hdev);
 }
 
@@ -808,9 +812,13 @@
 	hci_dev_lock(hdev);
 
 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
-	if (conn)
+	if (conn) {
 		clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
 
+		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
+			hci_sco_setup(conn, status);
+	}
+
 	hci_dev_unlock(hdev);
 }
 
@@ -915,20 +923,8 @@
 	} else
 		conn->state = BT_CLOSED;
 
-	if (conn->type == ACL_LINK) {
-		struct hci_conn *sco = conn->link;
-		if (sco) {
-			if (!ev->status) {
-				if (lmp_esco_capable(hdev))
-					hci_setup_sync(sco, conn->handle);
-				else
-					hci_add_sco(sco, conn->handle);
-			} else {
-				hci_proto_connect_cfm(sco, ev->status);
-				hci_conn_del(sco);
-			}
-		}
-	}
+	if (conn->type == ACL_LINK)
+		hci_sco_setup(conn, ev->status);
 
 	if (ev->status) {
 		hci_proto_connect_cfm(conn, ev->status);
@@ -1481,6 +1477,9 @@
 			else
 				conn->power_save = 0;
 		}
+
+		if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
+			hci_sco_setup(conn, ev->status);
 	}
 
 	hci_dev_unlock(hdev);
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 43fbf6b..44a6232 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -1152,7 +1152,7 @@
 	return err;
 }
 
-void rfcomm_cleanup_sockets(void)
+void __exit rfcomm_cleanup_sockets(void)
 {
 	debugfs_remove(rfcomm_sock_debugfs);
 
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 309b6c2..026205c 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -1153,7 +1153,7 @@
 	.tiocmset		= rfcomm_tty_tiocmset,
 };
 
-int rfcomm_init_ttys(void)
+int __init rfcomm_init_ttys(void)
 {
 	rfcomm_tty_driver = alloc_tty_driver(RFCOMM_TTY_PORTS);
 	if (!rfcomm_tty_driver)
@@ -1183,7 +1183,7 @@
 	return 0;
 }
 
-void rfcomm_cleanup_ttys(void)
+void __exit rfcomm_cleanup_ttys(void)
 {
 	tty_unregister_driver(rfcomm_tty_driver);
 	put_tty_driver(rfcomm_tty_driver);