xref: /openbmc/linux/net/bluetooth/hci_sysfs.c (revision ecc23d0a422a3118fcf6e4f0a46e17a6c2047b02)
1  // SPDX-License-Identifier: GPL-2.0
2  /* Bluetooth HCI driver model support. */
3  
4  #include <linux/module.h>
5  
6  #include <net/bluetooth/bluetooth.h>
7  #include <net/bluetooth/hci_core.h>
8  
9  static const struct class bt_class = {
10  	.name = "bluetooth",
11  };
12  
bt_link_release(struct device * dev)13  static void bt_link_release(struct device *dev)
14  {
15  	struct hci_conn *conn = to_hci_conn(dev);
16  	kfree(conn);
17  }
18  
19  static const struct device_type bt_link = {
20  	.name    = "link",
21  	.release = bt_link_release,
22  };
23  
hci_conn_init_sysfs(struct hci_conn * conn)24  void hci_conn_init_sysfs(struct hci_conn *conn)
25  {
26  	struct hci_dev *hdev = conn->hdev;
27  
28  	bt_dev_dbg(hdev, "conn %p", conn);
29  
30  	conn->dev.type = &bt_link;
31  	conn->dev.class = &bt_class;
32  	conn->dev.parent = &hdev->dev;
33  
34  	device_initialize(&conn->dev);
35  }
36  
hci_conn_add_sysfs(struct hci_conn * conn)37  void hci_conn_add_sysfs(struct hci_conn *conn)
38  {
39  	struct hci_dev *hdev = conn->hdev;
40  
41  	bt_dev_dbg(hdev, "conn %p", conn);
42  
43  	if (device_is_registered(&conn->dev))
44  		return;
45  
46  	dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle);
47  
48  	if (device_add(&conn->dev) < 0)
49  		bt_dev_err(hdev, "failed to register connection device");
50  }
51  
hci_conn_del_sysfs(struct hci_conn * conn)52  void hci_conn_del_sysfs(struct hci_conn *conn)
53  {
54  	struct hci_dev *hdev = conn->hdev;
55  
56  	bt_dev_dbg(hdev, "conn %p", conn);
57  
58  	if (!device_is_registered(&conn->dev)) {
59  		/* If device_add() has *not* succeeded, use *only* put_device()
60  		 * to drop the reference count.
61  		 */
62  		put_device(&conn->dev);
63  		return;
64  	}
65  
66  	/* If there are devices using the connection as parent reset it to NULL
67  	 * before unregistering the device.
68  	 */
69  	while (1) {
70  		struct device *dev;
71  
72  		dev = device_find_any_child(&conn->dev);
73  		if (!dev)
74  			break;
75  		device_move(dev, NULL, DPM_ORDER_DEV_LAST);
76  		put_device(dev);
77  	}
78  
79  	device_unregister(&conn->dev);
80  }
81  
bt_host_release(struct device * dev)82  static void bt_host_release(struct device *dev)
83  {
84  	struct hci_dev *hdev = to_hci_dev(dev);
85  
86  	if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
87  		hci_release_dev(hdev);
88  	else
89  		kfree(hdev);
90  	module_put(THIS_MODULE);
91  }
92  
93  static const struct device_type bt_host = {
94  	.name    = "host",
95  	.release = bt_host_release,
96  };
97  
hci_init_sysfs(struct hci_dev * hdev)98  void hci_init_sysfs(struct hci_dev *hdev)
99  {
100  	struct device *dev = &hdev->dev;
101  
102  	dev->type = &bt_host;
103  	dev->class = &bt_class;
104  
105  	__module_get(THIS_MODULE);
106  	device_initialize(dev);
107  }
108  
bt_sysfs_init(void)109  int __init bt_sysfs_init(void)
110  {
111  	return class_register(&bt_class);
112  }
113  
bt_sysfs_cleanup(void)114  void bt_sysfs_cleanup(void)
115  {
116  	class_unregister(&bt_class);
117  }
118