[Bluetooth] Add platform device for virtual and serial devices

This patch adds a generic Bluetooth platform device that can be used
as parent device by virtual and serial devices.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index 2830f58..8eebf9c 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -739,6 +739,7 @@
 
 	hdev->type = HCI_PCCARD;
 	hdev->driver_data = info;
+	SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
 
 	hdev->open     = bluecard_hci_open;
 	hdev->close    = bluecard_hci_close;
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index c9dba55..df7bb01 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -582,6 +582,7 @@
 
 	hdev->type = HCI_PCCARD;
 	hdev->driver_data = info;
+	SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
 
 	hdev->open     = bt3c_hci_open;
 	hdev->close    = bt3c_hci_close;
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index c889bf8..746ccca 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -502,6 +502,7 @@
 
 	hdev->type = HCI_PCCARD;
 	hdev->driver_data = info;
+	SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
 
 	hdev->open     = btuart_hci_open;
 	hdev->close    = btuart_hci_close;
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index be6eed1..0e99def 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -484,6 +484,7 @@
 
 	hdev->type = HCI_PCCARD;
 	hdev->driver_data = info;
+	SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
 
 	hdev->open     = dtl1_hci_open;
 	hdev->close    = dtl1_hci_close;
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index ea58900..aac67a3a 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -277,7 +277,6 @@
 
 	hdev->type = HCI_VHCI;
 	hdev->driver_data = vhci;
-	SET_HCIDEV_DEV(hdev, vhci_miscdev.dev);
 
 	hdev->open     = vhci_open_dev;
 	hdev->close    = vhci_close_dev;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index f685270..ae67b36 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -124,6 +124,7 @@
 
 	atomic_t 		promisc;
 
+	struct device		*dev;
 	struct class_device	class_dev;
 
 	struct module 		*owner;
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 729461f..788ea7a 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -48,7 +48,7 @@
 #define BT_DBG(D...)
 #endif
 
-#define VERSION "2.9"
+#define VERSION "2.10"
 
 /* Bluetooth sockets */
 #define BT_MAX_PROTO	8
@@ -307,14 +307,22 @@
 
 static int __init bt_init(void)
 {
+	int err;
+
 	BT_INFO("Core ver %s", VERSION);
 
-	sock_register(&bt_sock_family_ops);
+	err = bt_sysfs_init();
+	if (err < 0)
+		return err;
+
+	err = sock_register(&bt_sock_family_ops);
+	if (err < 0) {
+		bt_sysfs_cleanup();
+		return err;
+	}
 
 	BT_INFO("HCI device and connection manager initialized");
 
-	bt_sysfs_init();
-
 	hci_sock_init();
 
 	return 0;
@@ -324,9 +332,9 @@
 {
 	hci_sock_cleanup();
 
-	bt_sysfs_cleanup();
-
 	sock_unregister(PF_BLUETOOTH);
+
+	bt_sysfs_cleanup();
 }
 
 subsys_initcall(bt_init);
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 89918d2..7789e26 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -3,6 +3,8 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 
+#include <linux/platform_device.h>
+
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
@@ -197,9 +199,14 @@
 	.uevent		= bt_uevent,
 #endif
 };
-
 EXPORT_SYMBOL_GPL(bt_class);
 
+static struct bus_type bt_bus = {
+	.name	= "bluetooth",
+};
+
+static struct platform_device *bt_platform;
+
 int hci_register_sysfs(struct hci_dev *hdev)
 {
 	struct class_device *cdev = &hdev->class_dev;
@@ -211,6 +218,11 @@
 	cdev->class = &bt_class;
 	class_set_devdata(cdev, hdev);
 
+	if (!cdev->dev)
+		cdev->dev = &bt_platform->dev;
+
+	hdev->dev = cdev->dev;
+
 	strlcpy(cdev->class_id, hdev->name, BUS_ID_SIZE);
 	err = class_device_register(cdev);
 	if (err < 0)
@@ -233,10 +245,33 @@
 
 int __init bt_sysfs_init(void)
 {
-	return class_register(&bt_class);
+	int err;
+
+	bt_platform = platform_device_register_simple("bluetooth", -1, NULL, 0);
+	if (IS_ERR(bt_platform))
+		return PTR_ERR(bt_platform);
+
+	err = bus_register(&bt_bus);
+	if (err < 0) {
+		platform_device_unregister(bt_platform);
+		return err;
+	}
+
+	err = class_register(&bt_class);
+	if (err < 0) {
+		bus_unregister(&bt_bus);
+		platform_device_unregister(bt_platform);
+		return err;
+	}
+
+	return 0;
 }
 
 void __exit bt_sysfs_cleanup(void)
 {
 	class_unregister(&bt_class);
+
+	bus_unregister(&bt_bus);
+
+	platform_device_unregister(bt_platform);
 }