blob: 9874844a95a98cc3497dbab8379be536b02bd8a9 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/* Bluetooth HCI driver model support. */
3
Paul Gortmaker3a9a2312011-05-27 09:12:25 -04004#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07005
6#include <net/bluetooth/bluetooth.h>
7#include <net/bluetooth/hci_core.h>
8
Marcel Holtmannaef7d972010-03-21 05:27:45 +01009static struct class *bt_class;
Marcel Holtmann90855d72008-08-18 13:23:53 +020010
Marcel Holtmann90855d72008-08-18 13:23:53 +020011static void bt_link_release(struct device *dev)
12{
David Herrmann2dd10682012-02-09 21:58:34 +010013 struct hci_conn *conn = to_hci_conn(dev);
14 kfree(conn);
Marcel Holtmann90855d72008-08-18 13:23:53 +020015}
16
Bhumika Goyal9374bf12017-08-19 14:54:47 +053017static const struct device_type bt_link = {
Marcel Holtmann90855d72008-08-18 13:23:53 +020018 .name = "link",
Marcel Holtmann90855d72008-08-18 13:23:53 +020019 .release = bt_link_release,
20};
21
Gustavo F. Padovan6d438e32011-12-17 18:53:02 -020022/*
23 * The rfcomm tty device will possibly retain even when conn
24 * is down, and sysfs doesn't support move zombie device,
25 * so we should move the device before conn device is destroyed.
26 */
27static int __match_tty(struct device *dev, void *data)
Marcel Holtmann90855d72008-08-18 13:23:53 +020028{
Gustavo F. Padovan6d438e32011-12-17 18:53:02 -020029 return !strncmp(dev_name(dev), "rfcomm", 6);
30}
31
32void hci_conn_init_sysfs(struct hci_conn *conn)
33{
Marcel Holtmann457ca7b2009-05-05 13:09:01 -070034 struct hci_dev *hdev = conn->hdev;
Marcel Holtmann90855d72008-08-18 13:23:53 +020035
Gustavo F. Padovan6d438e32011-12-17 18:53:02 -020036 BT_DBG("conn %p", conn);
37
38 conn->dev.type = &bt_link;
39 conn->dev.class = bt_class;
40 conn->dev.parent = &hdev->dev;
41
42 device_initialize(&conn->dev);
43}
44
45void hci_conn_add_sysfs(struct hci_conn *conn)
46{
47 struct hci_dev *hdev = conn->hdev;
48
49 BT_DBG("conn %p", conn);
50
Marcel Holtmann457ca7b2009-05-05 13:09:01 -070051 dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle);
52
Marcel Holtmann90855d72008-08-18 13:23:53 +020053 if (device_add(&conn->dev) < 0) {
Marcel Holtmann2064ee32017-10-30 10:42:59 +010054 bt_dev_err(hdev, "failed to register connection device");
Marcel Holtmann90855d72008-08-18 13:23:53 +020055 return;
56 }
Marcel Holtmann384943e2009-05-08 18:20:43 -070057
58 hci_dev_hold(hdev);
Marcel Holtmann90855d72008-08-18 13:23:53 +020059}
60
Gustavo F. Padovan6d438e32011-12-17 18:53:02 -020061void hci_conn_del_sysfs(struct hci_conn *conn)
Marcel Holtmann90855d72008-08-18 13:23:53 +020062{
Marcel Holtmann90855d72008-08-18 13:23:53 +020063 struct hci_dev *hdev = conn->hdev;
64
Marcel Holtmanna67e8992009-05-02 18:24:06 -070065 if (!device_is_registered(&conn->dev))
66 return;
Roger Quadrosf3784d82009-04-23 14:50:54 +030067
Marcel Holtmann90855d72008-08-18 13:23:53 +020068 while (1) {
69 struct device *dev;
70
71 dev = device_find_child(&conn->dev, NULL, __match_tty);
72 if (!dev)
73 break;
Cornelia Huckffa6a702009-03-04 12:44:00 +010074 device_move(dev, NULL, DPM_ORDER_DEV_LAST);
Marcel Holtmann90855d72008-08-18 13:23:53 +020075 put_device(dev);
76 }
77
78 device_del(&conn->dev);
Marcel Holtmann384943e2009-05-08 18:20:43 -070079
Marcel Holtmann90855d72008-08-18 13:23:53 +020080 hci_dev_put(hdev);
81}
82
Marcel Holtmann90855d72008-08-18 13:23:53 +020083static void bt_host_release(struct device *dev)
Marcel Holtmanna91f2e32006-07-03 10:02:41 +020084{
David Herrmann2dd10682012-02-09 21:58:34 +010085 struct hci_dev *hdev = to_hci_dev(dev);
86 kfree(hdev);
David Herrmann46e06532012-01-07 15:47:21 +010087 module_put(THIS_MODULE);
Marcel Holtmannb219e3a2006-07-06 12:38:46 +020088}
89
Bhumika Goyal9374bf12017-08-19 14:54:47 +053090static const struct device_type bt_host = {
Marcel Holtmann90855d72008-08-18 13:23:53 +020091 .name = "host",
Marcel Holtmann90855d72008-08-18 13:23:53 +020092 .release = bt_host_release,
93};
Marcel Holtmanna91f2e32006-07-03 10:02:41 +020094
David Herrmann0ac7e702011-10-08 14:58:47 +020095void hci_init_sysfs(struct hci_dev *hdev)
96{
97 struct device *dev = &hdev->dev;
98
99 dev->type = &bt_host;
100 dev->class = bt_class;
101
David Herrmann46e06532012-01-07 15:47:21 +0100102 __module_get(THIS_MODULE);
David Herrmann0ac7e702011-10-08 14:58:47 +0200103 device_initialize(dev);
104}
105
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106int __init bt_sysfs_init(void)
107{
Marcel Holtmanna91f2e32006-07-03 10:02:41 +0200108 bt_class = class_create(THIS_MODULE, "bluetooth");
Marcel Holtmann27d35282006-07-03 10:02:37 +0200109
Rusty Russell8c6ffba2013-07-15 11:20:32 +0930110 return PTR_ERR_OR_ZERO(bt_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111}
112
Arnaud Patard860e13b2006-09-28 15:29:37 -0700113void bt_sysfs_cleanup(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114{
Marcel Holtmanna91f2e32006-07-03 10:02:41 +0200115 class_destroy(bt_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116}