xref: /linux/net/bluetooth/hci_sysfs.c (revision 546b928da0427b0d6c663cbb992bd7bfa9ac7971)
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 	struct device *parent = dev->parent;
17 
18 	kfree(conn);
19 	put_device(parent);
20 }
21 
22 static const struct device_type bt_link = {
23 	.name    = "link",
24 	.release = bt_link_release,
25 };
26 
27 /*
28  * The rfcomm tty device will possibly retain even when conn
29  * is down, and sysfs doesn't support move zombie device,
30  * so we should move the device before conn device is destroyed.
31  */
__match_tty(struct device * dev,const void * data)32 static int __match_tty(struct device *dev, const void *data)
33 {
34 	return !strncmp(dev_name(dev), "rfcomm", 6);
35 }
36 
hci_conn_init_sysfs(struct hci_conn * conn)37 void hci_conn_init_sysfs(struct hci_conn *conn)
38 {
39 	struct hci_dev *hdev = conn->hdev;
40 
41 	bt_dev_dbg(hdev, "conn %p", conn);
42 
43 	conn->dev.type = &bt_link;
44 	conn->dev.class = &bt_class;
45 	conn->dev.parent = get_device(&hdev->dev);
46 
47 	device_initialize(&conn->dev);
48 }
49 
hci_conn_add_sysfs(struct hci_conn * conn)50 void hci_conn_add_sysfs(struct hci_conn *conn)
51 {
52 	struct hci_dev *hdev = conn->hdev;
53 
54 	bt_dev_dbg(hdev, "conn %p", conn);
55 
56 	if (device_is_registered(&conn->dev))
57 		return;
58 
59 	dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle);
60 
61 	if (device_add(&conn->dev) < 0)
62 		bt_dev_err(hdev, "failed to register connection device");
63 }
64 
hci_conn_del_sysfs(struct hci_conn * conn)65 void hci_conn_del_sysfs(struct hci_conn *conn)
66 {
67 	struct hci_dev *hdev = conn->hdev;
68 
69 	bt_dev_dbg(hdev, "conn %p", conn);
70 
71 	if (!device_is_registered(&conn->dev)) {
72 		/* If device_add() has *not* succeeded, use *only* put_device()
73 		 * to drop the reference count.
74 		 */
75 		put_device(&conn->dev);
76 		return;
77 	}
78 
79 	/* If there are devices using the connection as parent reset it to NULL
80 	 * before unregistering the device.
81 	 */
82 	while (1) {
83 		struct device *dev;
84 
85 		dev = device_find_child(&conn->dev, NULL, __match_tty);
86 		if (!dev)
87 			break;
88 		device_move(dev, NULL, DPM_ORDER_DEV_LAST);
89 		put_device(dev);
90 	}
91 
92 	device_unregister(&conn->dev);
93 }
94 
bt_host_release(struct device * dev)95 static void bt_host_release(struct device *dev)
96 {
97 	struct hci_dev *hdev = to_hci_dev(dev);
98 
99 	if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
100 		hci_release_dev(hdev);
101 	} else {
102 		cleanup_srcu_struct(&hdev->srcu);
103 		kfree(hdev);
104 	}
105 	module_put(THIS_MODULE);
106 }
107 
reset_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)108 static ssize_t reset_store(struct device *dev, struct device_attribute *attr,
109 			   const char *buf, size_t count)
110 {
111 	struct hci_dev *hdev = to_hci_dev(dev);
112 
113 	if (hdev->reset)
114 		hdev->reset(hdev);
115 
116 	return count;
117 }
118 static DEVICE_ATTR_WO(reset);
119 
120 static struct attribute *bt_host_attrs[] = {
121 	&dev_attr_reset.attr,
122 	NULL,
123 };
124 ATTRIBUTE_GROUPS(bt_host);
125 
126 static const struct device_type bt_host = {
127 	.name    = "host",
128 	.release = bt_host_release,
129 	.groups = bt_host_groups,
130 };
131 
hci_init_sysfs(struct hci_dev * hdev)132 void hci_init_sysfs(struct hci_dev *hdev)
133 {
134 	struct device *dev = &hdev->dev;
135 
136 	dev->type = &bt_host;
137 	dev->class = &bt_class;
138 
139 	__module_get(THIS_MODULE);
140 	device_initialize(dev);
141 }
142 
bt_sysfs_init(void)143 int __init bt_sysfs_init(void)
144 {
145 	return class_register(&bt_class);
146 }
147 
bt_sysfs_cleanup(void)148 void bt_sysfs_cleanup(void)
149 {
150 	class_unregister(&bt_class);
151 }
152