diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2013-04-06 14:28:45 -0400 |
---|---|---|
committer | Gustavo Padovan <gustavo.padovan@collabora.co.uk> | 2013-04-17 02:03:43 -0400 |
commit | 2c8e1411e93391c5a78f55b09697a997474a4707 (patch) | |
tree | 3881d50853b94b260ba15b09e9c3b07a951fa482 /include | |
parent | 9c903e373c11f62d62bce1209f662ca92589a075 (diff) |
Bluetooth: l2cap: add l2cap_user sub-modules
Several sub-modules like HIDP, rfcomm, ... need to track l2cap
connections. The l2cap_conn->hcon->dev object is used as parent for sysfs
devices so the sub-modules need to be notified when the hci_conn object is
removed from sysfs.
As submodules normally use the l2cap layer, the l2cap_user objects are
registered there instead of on the underlying hci_conn object. This avoids
any direct dependency on the HCI layer and lets the l2cap core handle any
specifics.
This patch introduces l2cap_user objects which contain a "probe" and
"remove" callback. You can register them on any l2cap_conn object and if
it is active, the "probe" callback will get called. Otherwise, an error is
returned.
The l2cap_conn object will call your "remove" callback directly before it
is removed from user-space. This allows you to remove your submodules
_before_ the parent l2cap_conn and hci_conn object is removed.
At any time you can asynchronously unregister your l2cap_user object if
your submodule vanishes before the l2cap_conn object does.
There is no way around l2cap_user. If we want wire-protocols in the
kernel, we always want the hci_conn object as parent in the sysfs tree. We
cannot use a channel here since we might need multiple channels for a
single protocol.
But the problem is, we _must_ get notified when an l2cap_conn object is
removed. We cannot use reference-counting for object-removal! This is not
how it works. If a hardware is removed, we should immediately remove the
object from sysfs. Any other behavior would be inconsistent with the rest
of the system. Also note that device_del() might sleep, but it doesn't
wait for user-space or block very long. It only _unlinks_ the object from
sysfs and the whole device-tree. Everything else is handled by ref-counts!
This is exactly what the other sub-modules must do: unlink their devices
when the "remove" l2cap_user callback is called. They should not do any
cleanup or synchronous shutdowns.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Diffstat (limited to 'include')
-rw-r--r-- | include/net/bluetooth/l2cap.h | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 7b4cc5b98535..fb94cf13c777 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -584,6 +584,13 @@ struct l2cap_conn { | |||
584 | struct list_head chan_l; | 584 | struct list_head chan_l; |
585 | struct mutex chan_lock; | 585 | struct mutex chan_lock; |
586 | struct kref ref; | 586 | struct kref ref; |
587 | struct list_head users; | ||
588 | }; | ||
589 | |||
590 | struct l2cap_user { | ||
591 | struct list_head list; | ||
592 | int (*probe) (struct l2cap_conn *conn, struct l2cap_user *user); | ||
593 | void (*remove) (struct l2cap_conn *conn, struct l2cap_user *user); | ||
587 | }; | 594 | }; |
588 | 595 | ||
589 | #define L2CAP_INFO_CL_MTU_REQ_SENT 0x01 | 596 | #define L2CAP_INFO_CL_MTU_REQ_SENT 0x01 |
@@ -817,4 +824,7 @@ void __l2cap_physical_cfm(struct l2cap_chan *chan, int result); | |||
817 | void l2cap_conn_get(struct l2cap_conn *conn); | 824 | void l2cap_conn_get(struct l2cap_conn *conn); |
818 | void l2cap_conn_put(struct l2cap_conn *conn); | 825 | void l2cap_conn_put(struct l2cap_conn *conn); |
819 | 826 | ||
827 | int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user); | ||
828 | void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user); | ||
829 | |||
820 | #endif /* __L2CAP_H */ | 830 | #endif /* __L2CAP_H */ |